好家伙,nextTick,
(...这玩意,不太常用)
1.什么是nextTick
在Vue中,nextTick是一个用于异步执行回调函数的方法。
它在Vue更新DOM后被调用,以确保在下一次DOM更新渲染完成后执行回调函数。
而事实上,我们把队列处理的操作封装到了nexrTick方法中.
实际上,Vue在更新DOM时是异步执行的。
当你修改Vue实例的数据时,Vue会对依赖这些数据的虚拟DOM进行重新渲染,然后更新到真实的DOM上。
但是,DOM更新是在下一个事件循环中执行的,而不是立即执行。
所以,如果你想在DOM更新后执行一些操作,你就可以使用nextTick方法。
这个方法会将回调函数推入到微任务队列中,并在DOM更新后执行。
这样可以确保你在操作更新后的DOM,比如获取元素的宽高等,而不是得到修改前的值。
举一个非常简单的例子
- Vue.Mixin({ //全局
- created: function b() {
- // console.log('b----2')
- }
- })
- let vm = new Vue({
- el: '#app', //编译模板
- // data: {
- // },
- data() {
- // console.log(this)
- return {
- msg:'牛肉',
- arr: [1, 2, 3],
- }
- },
- created() {
- // console.log(555)
- }
- })
- console.log(vm.msg,"||直接打印msg的值")
- setTimeout(() => {
- //注意数据更新多次,vm._updata(vm._render()) 只需要执行一次
- vm.arr.push({b:5})
- vm.arr.push({b:6})
- console.log(vm.msg,"||计时器打印msg的值")
- vm.msg = '张三'
- vm.$nextTick(()=>{
- console.log(vm.msg,"||nextTick()方法打印msg的值")
- })
- }, 1000)
这里
可以看出来

nextTick()方法中的console确实拿到了最新的值
2.代码实现
给vm原型添加$nextTick方法
2.1.initState.js
- export function stateMixin(vm) {
- //列队批处理
- //1.处理vue自己的nextTick
- //2.用户自己的
- vm.prototype.$nextTick = function (cb) {
- // console.log(cb)
- nextTick(cb)
- }
- }
2.2.watcher.js
(此处为部分代码)
- let queue = [] // 将需要批量更新的watcher 存放到一个列队中
- let has = {}
- let pending = false
- //数组重置
- function flushWatcher() {
- queue.forEach(item => {
- item.run()})
- queue = []
- has = {}
- pending = false
- }
- function queueWatcher(watcher) {
- let id = watcher.id // 每个组件都是同一个 watcher
- // console.log(id) //去重
- if (has[id] == null) {//去重
- //列队处理
- queue.push(watcher)//将wacher 添加到列队中
- has[id] = true
- //防抖 :用户触发多次,只触发一个 异步,同步
- if (!pending) {
- //异步:等待同步代码执行完毕之后,再执行
- // setTimeout(()=>{
- // queue.forEach(item=>item.run())
- // queue = []
- // has = {}
- // pending = false
- // },0)
- nextTick(flushWatcher) // nextTick相当于定时器
- }
- pending = true
- }
- }
2.3.nextTicks.js
- let callback = []
- let pending = false
- function flush(){
- callback.forEach(cb =>cb())
- pending =false
- }
- let timerFunc
- //处理兼容问题
- //判断全局对象中是否存在Promise
- //看浏览器是否支持promise
- if(Promise){
- timerFunc = ()=>{
- Promise.resolve().then(flush) //异步处理
- }
- }else if(MutationObserver){ //h5 异步方法 他可以监听 DOM 变化 ,监控完毕之后在来异步更新
- let observe = new MutationObserver(flush)
- let textNode = document.createTextNode(1) //创建文本
- observe.observe(textNode,{characterData:true}) //观测文本的内容
- timerFunc = ()=>{
- textNode.textContent = 2
- }
- }else if(setImmediate){ //ie
- timerFunc = ()=>{
- setImmediate(flush)
- }
- }
- export function nextTick(cb){
- // 1vue 2
- // console.log(cb)
- //列队 [cb1,cb2]
- //此处,注意,我们要处理用户的nextTick()也要处理vue自己的nextTick
- callback.push(cb)
- //Promise.then() vue3
-
- if(!pending){
- timerFunc() //这个方法就是异步方法 但是 处理兼容问题
- pending = true
- }
- }