daily-plan icon indicating copy to clipboard operation
daily-plan copied to clipboard

2020-04-10日计划

Open sl1673495 opened this issue 4 years ago • 2 comments

关于 Vue 的 nextTick 实现

Vue源码详解之nextTick:MutationObserver只是浮云,microtask才是核心!

这篇文章又过了一遍,有了新的理解,原来浏览器可能会有多个task队列,其中用户对于ui的操作的task队列优先级可能比 postMessage 更高。 Vue在某个版本利用 postMessage 实现 nextTick 就出了问题。

比如用户一直在向下滚动视图并且触发 scroll 事件的话,由于这个事件是优先级更高的,可能导致本来应该触发的 nextTick 回调函数最差的情况下被延后了 1000ms 才执行。

如果用 microTask 队列来实现的话,则没有这个问题,因为 UI render 之前是一定会清空 microTask 队列的。一定是能赶在下一次的 UI render 之前执行完任务(比如 dom 变更)

关于 setTimeout 的一个发现

原来

setTimeout(() => {
  document.body.style.background = 'blue'
  setTimeout(() => {
    document.body.style.background = 'red'
  })
})

大概率是会触发两次浏览器的渲染的,我误以为由于他们之间的延迟不到 16ms,会被合并成一次。但是其实它会被作为两个 task,而 task 之间穿插了 UI render。

至于为什么有时候不更新,我就真的不知道了,可能是某种优化策略吧。

sl1673495 avatar Apr 09 '20 16:04 sl1673495

Vue 2.6 版本的 computed 实现

之前一直没调试,认知里的 computed 一直是 2.4 版本的,每次读取 computed 都会求值,但是只有值发生变化的时候才会去触发 render。

2.6 版本改动很大, 首先 computed watcher 会和它依赖的响应式的值共用一个 dep,并且会帮助这个 dep 去收集 渲染 watcher

所以 2.6 版本计算属性更新的路径是这样的:

响应式的值更新-> 同时通知 computed watcher渲染 watcher 更新 -> computed watcherdirty 设置为 true -> 视图渲染读取到 computed 的值,由于 dirty 所以 computed watcher 重新求值。

computed watcher 内部有个属性 dirty 开关来决定 computed 的值是需要重新计算还是直接复用之前的值。

以这样的一个例子来说:

computed: {
    sum() {
        return this.count + 1
    }
}

首先明确两个关键字:

「dirty」 从字面意义来讲就是 的意思,这个开关开启了,就意味着这个数据是脏数据,需要重新求值了拿到最新值。

「求值」 的意思的对用户传入的函数进行执行,也就是执行 return this.count + 1

  1. sum 第一次进行求值的时候会读取响应式属性 count,收集到这个响应式数据作为依赖。并且计算出一个值来保存在自身的 value 上,把 dirty 设为 false,接下来在模板里再访问 sum 就直接返回这个求好的值 value,并不进行重新的求值。
  2. count 发生变化了以后会通知 sum 所对应的 watcher 把自身的 dirty 属性设置成 true,这也就相当于把重新求值的开关打开来了。这个很好理解,只有 count 变化了, sum 才需要重新去求值。
  3. 那么下次模板中再访问到 this.sum 的时候,才会真正的去重新调用 sum 函数求值,并且再次把 dirty 设置为 false,等待下次的开启……

sl1673495 avatar Apr 09 '20 16:04 sl1673495

关于 <script> 标签是否会阻塞页面渲染的问题,昨天测试了下,把引用了 cdn 上的 vue 的 script 标签放在网页的头部,first paint 事件会等待下载完成后才执行,页面是确实会被阻塞的。

所以还是要放在 body底部。

sl1673495 avatar Apr 10 '20 01:04 sl1673495