1.执行代码
案例一
<script src="../../dist/vue.global.js"></script>
<div id="demo">
<h1>
<p>{{count}}</p>
</h1>
</div>
<script>
const { createApp, ref, toRefs, reactive, watch, onMounted, computed } = Vue
var app = createApp({
setup() {
var count = ref(1)
onMounted(() => {
count.value++;
})
return { count }
}
})
app.mount('#demo')
</script>
案例二
<script src="../../dist/vue.global.js"></script>
<div id="demo">
<h1>
<p ref="ppp">{{count}}</p>
</h1>
</div>
<script>
const { createApp, ref, toRefs, reactive, watch, onMounted, computed } = Vue
var app = createApp({
setup() {
var count = ref(1)
var ppp = ref(null)
onMounted(() => {
count.value++;
console.log(ppp.value.innerHTML);// 1
Vue.nextTick(() => {
console.log(ppp.value.innerHTML); // 2
})
})
return { count, ppp }
}
})
app.mount('#demo')
</script>
2.打断点
- 查找文件
packages\runtime-core\src\scheduler.ts
ctrl+f
输入function flushJobs(
,在函数内部打上断点
3.两个案例调用栈图如下
4.案例二代码分析
- 在执行patch递归时,会处理到
<p ref="ppp">{{count}}</p>
中的ref="ppp"
,这个就是setRef
- 触发
setRef
函数 - 触发
queueEffectWithSuspense
函数 - 触发
queuePostFlushCb
函数 - 触发
queueCb
函数 - 触发
queueFlush
函数,建立一个Promise微任务去执行flushJobs
- 触发
flushJobs
函数
function nextTick(
this,
fn
){
const p = currentFlushPromise || resolvedPromise
return fn ? p.then(this ? fn.bind(this) : fn) : p
}
const resolvedPromise = Promise.resolve()
let currentFlushPromise = null
function queueFlush() {
if (!isFlushing && !isFlushPending) {
isFlushPending = true
currentFlushPromise = resolvedPromise.then(flushJobs)
}
}