Vue中的nextTick原理解析

nextTick的使用场景

nextTick是全局vue的一个函数,在vue系统中,用于处理dom更新的操作。vue里面有一个watcher,用于观察数据的变化,然后更新dom,vue里面并不是每次数据改变都会触发更新dom,而是将这些操作都缓存在一个队列,在一个事件循环结束之后,刷新队列,统一执行dom更新操作。
通常情况下,我们不需要关心这个问题,而如果想在DOM状态更新后做点什么,则需要用到nextTick。在vue生命周期的created()钩子函数进行的DOM操作要放在Vue.nextTick()的回调函数中,因为created()钩子函数执行的时候DOM并未进行任何渲染,而此时进行DOM操作是徒劳的,所以此处一定要将DOM操作的JS代码放进Vue.nextTick()的回调函数中。而与之对应的mounted钩子函数,该钩子函数执行时所有的DOM挂载和渲染都已完成,此时该钩子函数进行任何DOM操作都不会有个问题。
nextTick源码分析

var nextTick=(function () {
    //存储需要触发的回调函数
    var callbacks=[];
    //是否正在等待的标志(false:允许触发在下次事件循环触发callbacks中的回调,
    // true: 已经触发过,需要等到下次事件循环)
    var pending=false;
    //设置在下次事件循环触发callbacks的触发函数
    var timerFunc;
    //处理callbacks的函数
    function nextTickHandler() {
        // 可以触发timeFunc
        pending=false;
        //复制callback
        var copies=callbacks.slice(0);
        //清除callback
        callbacks.length=0;
        for(var i=0;i<copies.length;i++){
            //触发callback的回调函数
            copies[i]();
        }
    }
    //如果支持promise,使用promise实现
    if(typeof Promise !=='undefined' && isNative(promise)){
        var p=Promise.resolve();
        var logError=function (err) {
            console.error(err);
        };
        timerFunc=function () {
            p.then(nextTickHandler).catch(logError);
            //iOS的webview下,需要强制刷新队列,执行上面的回调函数
            if(isIOS) {setTimeout(noop);}
        };
    //    如果Promise不支持,但支持MutationObserver
    //    H5新特性,异步,当dom变动是触发,注意是所有的dom都改变结束后触发
    } else if (typeof MutationObserver !=='undefined' && (
        isNative(MutationObserver) ||
        MutationObserver.toString()==='[object MutationObserverConstructor]')){
            var counter = 1;
            var observer=new MutationObserver(nextTickHandler);
            var textNode=document.createTextNode(String(counter));
            observer.observe(textNode,{
                characterData:true
            });
            timerFunc=function () {
                counter=(counter+1)%2;
                textNode.data=String(counter);
            };
    } else {
        //上面两种都不支持,用setTimeout
        timerFunc=function () {
            setTimeout(nextTickHandler,0);
        };
    }
    //nextTick接收的函数,参数1:回调函数 参数2:回调函数的执行上下文
    return function queueNextTick(cb,ctx) {
        //用于接收触发Promise.then中回调的函数
        //向回调函数中pushcallback
        var _resolve;
        callbacks.push(function () {
            //如果有回调函数,执行回调函数
            if(cb) {cb.call(ctx);}
            //触发Promise的then回调
            if(_resolve) {_resolve(ctx);}
        });
        //是否执行刷新callback队列
        if(!pending){
            pending=true;
            timerFunc();
        }
        //如果没有传递回调函数,并且当前浏览器支持promise,使用promise实现
        if(!cb && typeof  Promise !=='undefined'){
            return new Promise(function (resolve) {
                _resolve=resolve;
            })
        }
    }
})

详情内容点我

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值