注册
web

让用户愿意等待的秘密:实时图片预览

你有没有经历过这样的场景?点击“上传头像”,选了一张照片,页面却毫无反应——没有提示,没有图像,只有一个静默的按钮。你开始怀疑:是没选上?网速慢?还是系统出错了?于是你犹豫要不要再点一次,甚至直接关掉页面。

而如果在你选择文件的瞬间,一张清晰的缩略图立刻出现在眼前,哪怕后端还在处理,你也会安心地等待下去。

不是用户没耐心,而是他们需要一点“确定性”来支撑等待的理由。

图片预览,正是那个微小却关键的信号:你的操作已被接收,一切正在按预期进行。


得到程序正在运行的信号之后用户才会有等待的欲望。


今天,我们就来亲手实现一个图片预览功能。
先思考:要让一张用户选中的本地图片显示在网页上,我们到底需要做些什么?




第一步:我们要显示图片,那肯定得有个 <img> 标签吧?


没错。想在页面上看到图片,最直接的方式就是用 <img :src="xxx" />。但问题来了:用户刚从电脑里选了一张照片,这张照片还在他本地硬盘上,还没传到服务器,也没有公开 URL。那 src 该填什么?


这时候你可能会想:“能不能把这张本地文件直接塞进 src?”

答案是:不能直接塞 File 对象,但——我们可以把它“变成”一个 URL。




第二步:用户选了图,我们怎么拿到它?


通常我们会用 <input type="file" accept="image/*"> 让用户选择图片。在 Vue 中,为了能“拿到”这个 input 元素本身(而不仅仅是它的值),我们会用到 ref


<input 
type="file"
ref="uploadImage"
accept="image/*"
@change="updateImageData"
/>

这里,ref="uploadImage" 就像给这个 input 贴了个标签。之后在 script 里,我们就能通过 uploadImage.value 拿到它的真实 DOM 引用。


于是,在 updateImageData 函数里,我们可以这样取到用户选中的文件:


const input = uploadImage.value;
const file = input.files[0]; // 用户选的第一张图

注意:不是 input.file,而是 input.files —— 这是一个常见的笔误,也是很多初学者卡住的地方。




第三步:有了 File 对象,怎么变成 <img> 能识别的 src


现在我们手里有一个 File 对象,但它不能直接赋给 img.src。我们需要把它转成一种浏览器能直接渲染的格式。


这时候,FileReader 就登场了。


const reader = new FileReader();
reader.readAsDataURL(file);

readAsDataURL 会把文件内容读取为一个 Data URL,格式类似:


data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...

这串字符串可以直接作为 <img>src!是不是很巧妙?


那什么时候能拿到这个结果呢?FileReader 是异步的,所以我们监听它的 onloadend 事件:


reader.onloadend = (e) => {
imgPreview.value = e.target.result; // 这就是 Data URL
}

而我们的模板中早已准备好了一个 <img>


<img :src="imgPreview" alt="" v-if="imgPreview" />

imgPreview 有值时,图片就自动显示出来了!




完整逻辑串起来


把这些碎片拼在一起,整个流程就清晰了:



  1. 用户点击 input 选择图片;
  2. @change 触发 updateImageData
  3. 通过 ref 拿到 input,取出 files[0]
  4. FileReader 读取为 Data URL;
  5. 把结果存到响应式变量 imgPreview
  6. Vue 自动更新 <img :src="imgPreview">,图片就出来了。

这整个过程完全在前端完成,不需要上传到服务器,也不依赖任何第三方库——只用了浏览器原生 API 和 Vue 的响应式系统。




最后:完整实例


在vue中实现图片预览的完整代码及效果



作者:烟袅破辰
来源:juejin.cn/post/7585534343562608690

0 个评论

要回复文章请先登录注册