zoukankan      html  css  js  c++  java
  • VUE的$nextTick

    1.nextTick源码分析

      function nextTick (cb, ctx) {var _resolve;
        callbacks.push(function () {
          if (cb) {
            try {
              cb.call(ctx);
            } catch (e) {
              handleError(e, ctx, 'nextTick');
            }
          } else if (_resolve) {
            _resolve(ctx);
          }
        });
        if (!pending) {
          pending = true;
          timerFunc();
        }
        // $flow-disable-line
        if (!cb && typeof Promise !== 'undefined') {
          return new Promise(function (resolve) {
            _resolve = resolve;
          })
        }
      }

    callbacks

    多次nextTick,会在异步任务执行(Promise.then,MutationObserver,setImmediate,setTimeout)之前将多次nextTick的回调函数收集到callbacks

    pending

    因为会有多个地方都调用的nextTick的方法,使用pending用来控制timerFunc(执行nextTick回调函数队列)执行成功后才能再次调用timerFunc

      if (typeof Promise !== 'undefined' && isNative(Promise)) {
        var p = Promise.resolve();
        timerFunc = function () {
          p.then(flushCallbacks);
          // In problematic UIWebViews, Promise.then doesn't completely break, but
          // it can get stuck in a weird state where callbacks are pushed into the
          // microtask queue but the queue isn't being flushed, until the browser
          // needs to do some other work, e.g. handle a timer. Therefore we can
          // "force" the microtask queue to be flushed by adding an empty timer.
          if (isIOS) { setTimeout(noop); }
        };
        isUsingMicroTask = true;
      } else if (!isIE && typeof MutationObserver !== 'undefined' && (
        isNative(MutationObserver) ||
        // PhantomJS and iOS 7.x
        MutationObserver.toString() === '[object MutationObserverConstructor]'
      )) {
        // Use MutationObserver where native Promise is not available,
        // e.g. PhantomJS, iOS7, Android 4.4
        // (#6466 MutationObserver is unreliable in IE11)
        var counter = 1;
        var observer = new MutationObserver(flushCallbacks);
        var textNode = document.createTextNode(String(counter));
        observer.observe(textNode, {
          characterData: true
        });
        timerFunc = function () {
          counter = (counter + 1) % 2;
          textNode.data = String(counter);
        };
        isUsingMicroTask = true;
      } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
        // Fallback to setImmediate.
        // Technically it leverages the (macro) task queue,
        // but it is still a better choice than setTimeout.
        timerFunc = function () {
          setImmediate(flushCallbacks);
        };
      } else {
        // Fallback to setTimeout.
        timerFunc = function () {
          setTimeout(flushCallbacks, 0);
        };
      }
    function flushCallbacks () {
        pending = false;
        var copies = callbacks.slice(0);
        callbacks.length = 0;
        for (var i = 0; i < copies.length; i++) {
          copies[i]();
        }
      }

    flishCallbacks

    pending置为false,可以在下一次的nextTick执行时能调用timerFunc

    依次执行callbacks收集的回调函数

    2.data更新后不能立即获取到dom信息需要使用nextTick

      function queueWatcher (watcher) {
        var id = watcher.id;
        if (has[id] == null) {
          has[id] = true;
          if (!flushing) {
            queue.push(watcher);
          } else {
            // if already flushing, splice the watcher based on its id
            // if already past its id, it will be run next immediately.
            var i = queue.length - 1;
            while (i > index && queue[i].id > watcher.id) {
              i--;
            }
            queue.splice(i + 1, 0, watcher);
          }
          // queue the flush
          if (!waiting) {
            waiting = true;
    
            if ( !config.async) {
              flushSchedulerQueue();
              return
            }
            nextTick(flushSchedulerQueue);
          }
        }
      }
      Watcher.prototype.update = function update () {
        /* istanbul ignore else */
        if (this.lazy) {
          this.dirty = true;
        } else if (this.sync) {
          this.run();
        } else {
          queueWatcher(this);
        }
      };

    queueWatcher

    将需要更新的watcher收集起来,使用nextTick异步更新dom

    has[id]

    根据watcher的id判断queue是否已存在相同的watcher

    如果不存在则进行收集操作

    waiting
    因为queueWatcher也是多次调用,所以使用waiting来限制调用queueWatcher时在flushSchedulerQueue调用执行结束之前flushSchedulerQueue只调用
  • 相关阅读:
    1130 Infix Expression (25分)
    1131 Subway Map (30分)
    1132 Cut Integer (20分)
    1133 Splitting A Linked List (25分)
    1134 Vertex Cover (25分)
    1135 Is It A Red-Black Tree (30分)
    tensorflow 1.0的部分项目配置匹配
    1136 A Delayed Palindrome (20分)
    谷粒商城Redisson分布式锁(二十四)
    谷粒商城缓存(二十三)
  • 原文地址:https://www.cnblogs.com/wangxirui/p/15774808.html
Copyright © 2011-2022 走看看