异步队列渲染

上一篇文章是在vue2.0 中通过Object.defineProperty去拦截并监听数据变化的响应式原理,这篇文章将会沿着图谱继续深入探索,在依赖被通知变化了之后,会触发vue当中的异步渲染队列,这里我们就是要研究以下几点:

  1. 为什么要设计成异步渲染队列
  2. 渲染是如何实现的
  3. 因为异步渲染队列而产生的nextTick, 并了解nextTick的使用场景

对上次的代码做一个改造,使得模板依赖的变量增加时,如下面这样

let x = ref(1);
let y = ref(1);
let z = ref(1); onXChanged(() => {
console.log(`x: ${x.value}, y: ${y.value}, z: ${z.value}`);
}); x.value = 2;
y.value = 3;
z.value = 4;

控制台打印的结果如下:

我们可以看出x, y, z 的更改分别被执行了1次,那这些数据都是存在于模板中的,所以我们会认为这个模板被渲染了3次。那实际项目中,  多次渲染就产生很多的开销了。 所以从上面的这个例子我们发现,当模板中存在多出变量依赖的时候,每一个变量修改的时候,都会导致一次渲染,是否可以优化?

我们可以思考下实际工作中遇到的场景:

平时我们工作的时候,如果每隔一段时间,也许是5min或者10min,都会有一个策划向你提出需求时,或者一个新员工向你请教问题,或者一个测试人员向你提出bug, 如果这种频率出现很高,那我相信它一定会占用你的正常编码时间,使得你更加不能专注的完成你的本职工作了,那么我们一般可能都会选择把他们要做的事情先放到一边,让他们等一等,和自己约定一个时间,也许是45分钟或者1个小时,那么可以让自己在这段时间更加专注自己的本职工作,然后再去处理其他的事情。

其实vue中异步更新队列, 逻辑也是差不多的。当我们在一个函数块中包含对多个变量的依赖时,可以将这些依赖放入一个队列中,等到当前函数更新一次完成后,在进行批量的渲染操作,下面是具体的实现代码

(function () {
// let f = n => n * 100 + 200;
let active; let watch = function (cb) {
active = cb;
active();
active = null;
}
// 需要有个队列来存储各项任务
let queue = [];
// 通过微任务方式去执行队列中的任务
let nextTick = cb => Promise.resolve().then(cb);
// 将任务添加到队列
let queueJob = job => {
if (!queue.includes(job)) {
queue.push(job)
nextTick(flushJobs)
}
} // 执行队列中的任务
let flushJobs = () => {
let job;
while ((job = queue.shift()) !== undefined) {
job()
}
} // 收集更多依赖
class Dep {
// 依赖收集,将响应依赖添加到deps中
constructor() {
this.deps = new Set();
} depend() {
if (active) {
this.deps.add(active)
}
}
// 通知依赖更新
notify() {
// 将任务加到队列中
this.deps.forEach(dep => queueJob(dep))
}
} let ref = initValue => {
let value = initValue;
let dep = new Dep(); return Object.defineProperty({}, "value", {
get() {
dep.depend();
return value;
},
set(newValue) {
value = newValue;
dep.notify()
}
})
} let x = ref(1);
let y = ref(1);
let z = ref(1); watch(() => {
console.log(`x: ${x.value}, y: ${y.value}, z: ${z.value}`);
}); x.value = 2;
y.value = 3;
z.value = 4;
})()

测试结果如下:

这样我们可以让所以依赖更新完后,模板重新渲染一次

上面的 nextTick 返回一个Promise,需要注意的是在下次Dom更新循环结束之后执行延迟回调。

在 Vue中会有两种场景:

  1. Vue.nextTick([callback,context])
  2. vm.$nextTick([callback])
  • 将回调延迟到下次DOM更新循环之后执行。
  • 通常用于在修改数据之后使用这个方法,在回调中获取更新后的DOM
  • 实例中的方法会将callback的this 会自动绑定到实例上
  • 在生命周期钩子函数中mounted和updated直接执行的代码并不能保证子组件有完全的挂载或者更新,这个时候我们可以使用this.$nextTick(function(){})在整个视图都渲染完成后进行一些操作,这个过程是可靠的。

总结

这篇文章主要是对Vue异步渲染队列的研究,我们可以看出主要是对于模板性能的优化,所以产生了异步渲染队列的概念,同样产生了Vue.nextTick 的api,我们可以通过api去处理在模板更心之后,或者子组件更i性能后的逻辑。
 

免责声明

本文只是在学习Vue 异步渲染中的一些笔记,文中的资料也会涉及到引用,具体出处不详,商业用途请谨慎转载。

最新文章

  1. 利用AOP与ToStringBuilder简化日志记录
  2. 20145212《Java程序设计》实验报告二 《 Java面向对象程序设计》
  3. Unity3D 角色(物体) 移动方法 合集
  4. java.lang.StackOverflowError: stack size 8MB
  5. iOS8之后CoreLocation定位的使用
  6. 由href return false 来看阻止默认事件
  7. JBOSS EAP 6 系列五 Managed domains 管理域最主要的功能是“统一部署,统一配置”
  8. 内连接、左外连接、右外连接、全外连接、交叉连接(CROSS JOIN)-----小知识解决大数据攻略
  9. Java面试 32个核心必考点完全解析
  10. Delphi中Inputbox 和Inputquery 函数的使用
  11. [转]MYSQL性能查看(命中率,慢查询)
  12. .Net程序员 初学Ubuntu ,配置Nignix
  13. java 基础响应体定义 - 通用
  14. 2006 ACM 求奇数的和
  15. IO调度算法的选择
  16. Hadoop---集群的时间同步
  17. Linux内核分析作业第三周
  18. nginx做http向https的自动跳转
  19. R语言学习——欧拉计划(11)Largest product in a grid
  20. springboot的全局异常通知

热门文章

  1. 移动开发之h5学习大纲
  2. Linux学习 - 正则表达式
  3. Alamofire-5.0.0 以上报错
  4. 【C#】【MySQL】C#连接MySQL数据库(二)解析
  5. OAuth2.0实战:认证、资源服务异常自定义!
  6. pipeline是什么?
  7. InnoDB学习(五)之MVCC多版本并发控制
  8. 虎符2021线下赛pwn writeup
  9. ConfigParser模块,主要应用于对php.ini等格式的配置文件内容读取和生成。删改较少用
  10. mobx在react的使用