Vue源码:nextTick批量异步更新

Vue.js 实现了一个 nextTick 函数,传入一个 cb ,这个 cb 会被存储到一个队列中,在下一个 tick 时触发队列中的所有 cb 事件。

Vue源码中根据不同平台,使用不同的方式开启异步队列。具体实现可查看 next-tick.js

  • 支持Promise,使用Promise.resolve().then(flushCallbacks)
  • PhantomJS and iOS 7.x 使用MutationObserver
  • Internet Explorer 10 使用 setImmediate
  • 其他 使用 setTimeout
输入 
  let watch1 = new Watcher();
  let watch2 = new Watcher();

  watch1.update();
  watch1.update();
  watch2.update();
---------------------------------------------
输出(不采用批量异步更新)  
watch1 update
watch1视图更新啦~
watch1 update
watch1视图更新啦~
watch2 update
watch2视图更新啦~
----------------------------------------------
    (采用批量异步更新)
watch1 update
watch1 update
watch2 update
watch1视图更新啦~
watch2视图更新啦~
复制代码
let uid = 0;

class Watcher {
  constructor(){
    this.id = ++uid;
  }

  update() {
    console.log('watch' + this.id + ' update');
    //把需要更新的渲染watcher放入队列
    queueWatcher(this);
  }

  run(){
    console.log('watch' + this.id + ' 视图更新了');
  }
}

let callbacks = [];
let queue = [];
let pending = false;
let waiting = false;
let timerFunc;
let has = {};


function queueWatcher(watcher) {
  //这要打一个断点,不然看不到push watcher2的过程
  debugger;
  let id = watcher.id;
  if (has[id] == null) {
    has[id] = true;
    queue.push(watcher);

    if (!waiting) {
      waiting = true;
      /*开启一个异步队列*/
      nextTick(flushSchedulerQueue);
    }
  }

}

timerFunc=()=>{
  /*主线程执行完后,执行flushCallbacks函数*/
  Promise.resolve().then(flushCallbacks);
}

function nextTick(cb) {
  callbacks.push(cb);

  if (!pending) {
    pending=true
    timerFunc();
  }
}
/*执行flushSchedulerQueue*/
function flushCallbacks() {
  pending = false;
  const copies = callbacks.slice(0);
  callbacks.length = 0;
  for (let i = 0; i < copies.length; i++) {
    copies[i]();

  }

}


/*批量执行watcher.run*/
function flushSchedulerQueue() {
  let watcher, id;
  for (let i = 0; i < queue.length; i++) {
    watcher = queue[i];
    id = watcher.id;
    has[id] = null;
    watcher.run();
  }
  waiting = false;
}

(function () {
  debugger;
  let watch1 = new Watcher();
  let watch2 = new Watcher();

  watch1.update();
  watch1.update();
  watch2.update();
})();
复制代码

参考:juejin.im/book/5a3666…

转载于:https://juejin.im/post/5cd3d2ef6fb9a0322d04a194

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值