当前位置: 首页 > Web前端 > vue.js

【笔记】Vue-2-异步更新队列(nextTick分析)

时间:2023-03-31 16:13:32 vue.js

当模板依赖多个变量时,每个变量变化都会触发一次更新基于上一篇文章的Vue响应式原理,在下面的代码中,模板tpl依赖于三个变量x、y、z,其中一个变化会触发变化,所以会输出三次。letactiveletwatch=(cb)=>{active=cbactive()active=null//避免重复收集}classDep{//Set数据结构类似于数组,但成员是唯一的//通过newStructure生成Set数据constructor(){this.deps=newSet()}depend(){//依赖集合if(active){//通过add()方法向Set结构添加成员this.deps.add(active)}}notify(){//触发this.deps.forEach(dep=>dep())}}letref=initValue=>{letvalue=initValueletdep=newDep()returnObject.defineProperty({},'value',{get(){dep.depend()返回值},set(newValue){value=newValuedep.notify()}})}letx=ref(1)lety=ref(2)letz=ref(3)watch(()=>{lettpl=`hello${x.value}${y.value}${z.value}
`document.write(tpl)})x.value=2y.value=2z.value=2/*输出hello123hello223hello223hello222修改三次,输出三次*/如何优化?在一个功能块中包含对多个变量的依赖依赖的时候,可以把这些依赖放到一个队列中,在功能块执行完之后,进行批量渲染操作。microtask会在macrotask执行完毕后立即执行,所以最后的操作可以放到一个microtask中,这里使用Promise.resolve().then()来实现letactiveletwatch=(cb)=>{active=cbactive()active=null//避免重复收集}//队列,用来存放任务letqueue=[]//异步操作,会在同步操作之后执行letnextTick=cb=>Promise.resolve().then(cb)//添加任务到队列中letqueueJob=job=>{if(!queue.includes(job)){queue.push(job)//添加之后,放到一个异步任务中执行nextTick(flushJobs)}}//执行任务letflushJobs=()=>{letjobwhile(queue.length>0){job=queue.shift()job&&job()}}classDep{//设置数据结构类似到一个数组,但是成员都是唯一的//通过newconstructor()生成Set数据结构{this.deps=newSet()}depend(){//依赖集合if(active){//通过添加到Setadd()方法添加结构体成员this.deps.add(active)}}notify(){//触发//先放入队列this.deps.forEach(dep=>queueJob(dep))}}letref=initValue=>{letvalue=initValueletdep=newDep()returnObject.defineProperty({},'value',{get(){dep.depend()返回值},set(newValue){value=newValuedep.notify()}})}letx=ref(1)lety=ref(2)letz=ref(3)watch(()=>{lettpl=`hello${x.value}${y.value}${z.value}
`文档.write(tpl)})x.value=2y.value=2z.value=2/*输出hello123hello222三个赋值,只有一个函数进入队列,所以最后只会执行一次*/static方法:Vue.nextTick([callback,context])实例方法:vm.$nextTick([callback])这是下一个DOM更新周期结束后执行延迟回调的Vue实例。一般在修改数据后使用,在回调中获取更新的DOMmounted(){this.$nextTick(()=>{//这段代码会在当前组件和所有子组件挂载完成后执行})}