做的一个需求,其中有一个是实现类似于下图的一个图片上传效果:
从本地上传图片到服务器,然后服务器响应返回这个图片在服务器上的链接地址,将这个链接地址所对应的图片显示到屏幕上,并且在此图片资源完全下载下来之前,呈现一个动态 loading
的展位图,直到图片完全下载后进行替换
小tip
这是个很常见的需求,关键点在于检测图片的加载完成事件,一般的做法是,先将 img
标签的 src
属性指向一个当图片加载完成后,再将 src
指向真正的链接即可
const img = new Image()
// 真实图片地址
const realSrc = 'http://a.com/real.png'
img.src = realSrc
img.onload = () => {
// domImgElement 为 img 的 HTML DOM对象
domImgElement.src = realSrc
}
这种做法是没什么问题的,大多数情况下也都是这么做的,不过由于我擅(xian)长(de)思(dan)考(teng),然后就想到一个小问题
我手头的这个需求是基于 vue
,在页面渲染完毕之后,再想改变页面上的内容,就需要重新渲染一遍页面,尽管 vue
存在 vnode
的概念,更新速度很快,但就算再快都还是要把整个页面刷一遍的,这个过程无论如何是跑不掉的,如果页面上存在十几张甚至几十张类似于上面那种图片异步加载效果,那岂不是要改变几十次 data
值,vue
内部就要对应 patch
几十次,然后页面也就跟着整个更新几十次,想想都觉得可怕
每多 patch
一次 vnode tree
,每多更新一次页面,都将引起 CPU
和 GPU
的能耗升高,日积月累四舍五入那就是一个庞大而隐形的能源消耗黑洞,对个人的发展、对公司的财务、对地球的温室效应都将是一个沉重的负担!
更何况,一般这种列表类型的图片数据,都是存在于一个数组中,每当有图片下载完毕,在替换 src
之前,还要先根据某个标志位,例如图片 id
或者 url
来从这个图片数组中找到对应的图片,然后才能进行替换,而且这一步还要注意vue
不自动对嵌套对象的属性进行响应式操作的问题:
loadImg (imgId) {
const img = new Image()
// 真实图片地址
const realSrc