首页 > 编程语言 >Vue源码学习(十三):nextTick()方法

Vue源码学习(十三):nextTick()方法

时间:2023-10-22 22:58:15浏览次数:32  
标签:nextTick Vue console DOM vm 源码 let pending

好家伙,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
    }
}

 

 

 

 

标签:nextTick,Vue,console,DOM,vm,源码,let,pending
From: https://www.cnblogs.com/FatTiger4399/p/17780739.html

相关文章

  • BUG:net::ERR_CONNECTION_REFUSED(前端Vue2、后端FastAPI)
    BUG场景一个前后端分离的项目,前端使用Vue2框架,后端使用FastAPI,前端想要传输图片给后端,使用的相关接口为:'http://10.96.67.161:8081/uploadImg/'后端FastAPI运行的代码为:if__name__=='__main__':uvicorn.run(app="main:app",host="localhost",port=8081,reload=Tr......
  • vue
    1.文本:{{data}}注:①.用双大括号{{}}引住的内容被称为"Mustache"语法.2.原始html:<divv-html="data"></div>3.属性:<divv-bind:id="testId"></div>注:①.如chcked值绑定.4.表达式:{{num+1}}{{ok?'1':'0......
  • springboot+vue学习(2)
    1、ref :为子组件指定一个索引ID,给元素或者组件注册引用信息。refs是一个对象,包含所有的ref组件。<divid="parent"><user-profileref="profile"></user-profile>(子组件)</div>varparent=newVue({el:'#parent'})//访问子组件varchild=parent.$ref......
  • springboot+vue学习
    最近遇到一个问题,在一个页面需要动态渲染页面内的表单,其中包括checkbox表单类型,并且使用Element组件UI时,此时v-model绑定的数据也是动态生成的例如:定义的data的form里面是空对象,需要动态生成里面的keyexportdefault{data(){return{form:{}......
  • npm安装datav-vue3(一个大屏边框和装饰组件)后报错Failed to resolve entry for packa
    原因:个人认为应该是npm上的版本比较低,因为弄好后装饰只能用到第8个,后面的都没有,查看package.json里它的版本为^0.0.0-test.1672506674342,也就是说还没有正式版,在官方的说明里也有体现---[目前还处于Alpha阶段,所有的API及Props都可能在后续迭代中发生变化]介绍|DataV......
  • 这个收款单系统,我只想说很丝滑!第四方支付源码分享
    一、系统功能支持不同行业的收款单需求:如大学院校、物业、供热、停车等支持商户自定义表单字段一键生成收款单前后台代码批量导入创建收款单批量导出对账单等功能支持接入多个支付渠道、有大型银行的接口支持系统稳定高性能、上线两周交易额过亿二、业务场景2023年的移......
  • 14_数据结构与集合源码
    ......
  • [Vue]事件修饰符
    Vue中的事件修饰符:1.prevent:阻止默认事件(常用);2.stop:阻止事件冒泡(常用);3.once:事件只触发一次(常用);4.capture:使用事件的捕获模式;5.self:只有event.target是当前操作的元素是才触发事件;6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;          一......
  • 使用 Ant Design Vue 你可能会遇到的14个问题
    公司有一个新需求,在原来项目基础上开发,项目中使用AntDesignVue,版本是1.X,在此记录下遇到的问题;对于没有使用过或者使用程度不深的同学来说,希望可以帮助你在开发中遇到问题时有个参考。对于已经熟练使用的同学,可能这些问题都遇到过,欢迎大家在评论区补充。1、实现对下拉框显示......
  • Vue.js框架:vue3版本引入使用element-ui
    一、引入element-pluselement-ui只支持vue2,vue3需要引入element-plus进行使用,两个分别对应vue2和3两个版本,各自独立,无法跨级兼容。地址:https://element-plus.gitee.io/在vue3项目终端里使用以下命令引入该依赖:npminstallelement-plus--save二、修......