该是时候开始行动了
Vue3.0beta了离正式发布还有一段时间,趁着还没发布3.0感觉熟悉一波,以不至于3.0发布之后更看不动了。
我们需要fork一份代码,并下载下来,延着package.json的入口进行寻找需要查看的源码。
(ps:怎么寻找源码入口可以去google一下)
一起看代码
接下来,请各位同学翻到 /src/core/util/next-tick.js
首先出现在我们画面里面的为 flushCallbacks 函数运行起来步骤如下:
1.设置
pending为false
2.常量copies接收来自callbacks.slice(0)的返回
3.把数组callbacks设为空数组
4.遍历copies执行函数
中间的callbacks.slice(0)这一步或许有些同学看不懂,为此我来举个例子:
const tryArr = [1,2,3];
const newArr = tryArr.slice(0); // newArr = [1,2,3]
tryArr.length = 0; // tryArr = []
tryArr.slice(0) 截取的是从数组下标0开始项,并返回赋值给newArr。
接着我们继续往下看(ps:英文注释因为截图的原因被我删除了)
1.
Promise
2.MutationObserver
3.setImmediate
4.setTimeout
我们首先看看Promise里面它做了什么
const p = Promise.resolve() // Promise {<resolved>: undefined}
接着为函数赋值并给p.then设置为flushCallbacks函数,以及在IOS会导致Promise.then不会完全中断,所以需要做一些其他工作,例如处理计时器,因此我们可以“强制”通过添加空计时器来刷新微任务(microtask)队列。(noop根据路径找到后为一个空函数)
MutationObserver()接收一个回调函数,它会在指定的DOM发生变化时被调用.
而要触发DOM的变化可以用到了new MutationObserver().observe函数,它接收一个DOM,以及config配置,其中characterData表示DOM节点的值更改时是否调用的回调函数。至此关于nextTick我们已经看完了,但是有的同学可能还是不怎么懂为什么,那接着就来说说。
宏任务微任务
我们先来看一个例子:
console.log('开饭啦,我是第一位')
async function eatFoot() {
await eatFoot2();
console.log('我是第二位');
}
eatFoot();
new Promise(resolve => {
console.log('我是第三位');
resolve();
}).then(()=>console.log('加一位'))
async function eatFoot2() {
console.log('我是第四位');
}
它们执行后的顺序为:开饭啦,我是第一位 -> 我是第四位 -> 我是第三位 -> 加一位 -> 我是第二位。
这是为什么呢?我们来看看它们的执行顺序:
1.首先执行了第一位的console
2.接着执行eatFoot遇到await eatFoot2这里await表示为让出线程的意思,打印第四位
3.这时同步代码执行完后就该到异步代码了,所以执行到了Promise打印第三位
4.因为执行了resolve所以又进入了微任务的环境就走到了then里面,打印加一位
5.最后异步以及微任务没有了就返回回来await上面,打印第二位
这个顺序也就是Event Loop的执行顺序:
1.运行同步代码(宏任务 macrotask)
2.运行完所有同步代码后,再去看看有没有异步代码需要执行
3.运行所有微任务(microtask)
4.运行完所有微任务后,继续新的Event Loop,以及执行宏任务中的异步代码
到这里为止你觉得你可以知道下面这个最后为什么了吗
new Vue({
data(){
return {
food: '等待吃饭中...',
}
},
methods: {
foodStatus() {
this.food = "等一下"
this.$nextTick(() => {
this.food = '开饭'
})
this.food = '等一下'
}
}
mounted(){
this.foodStatus()
}
})
小结
表示写作的功底还有待提升,以上所写的内容如有疑问欢迎留言,希望对各位兄弟有帮助!