编程知识 cdmana.com

Learn more about nexttick in Vue

Vue in nextTick Use

stay vue Under development , We sometimes need to get dom Information after element update , When we assign a value to a variable, we immediately get dom Element information , It is usually obtained by updating the previous , Here we need the help of nextTick This api. The official example is as follows

//  Modifying data 
vm.msg = 'Hello' 
//  here DOM  Not updated yet  

//  recommend 
Vue.nextTick(function () { 
    //  here  DOM  Updated  
}) 

//  Not recommended 
Vue.nextTick().then(function () {
    //  here  DOM  Updated  
})
 Copy code 

Here we recommend the first way to write , stay nextTick On the principle of , Does not necessarily return a Promise, It could be through MutationObserver、setImmediate or setTimeout Realization .

Vue.nextTick() This method is in the event loop , Not necessarily micro or macro tasks , Its principle is Promise and MutationObserver It's a micro task , and setImmediate and setTimeout Belongs to macro task .

Vue in nextTick Principle analysis of

When we're in Vue Use in nextTick() when , Will first define callbacks Array ( Put the need in dom The content to be executed after the element update is placed in callbacks In the queue , In order to offer dom Execute after element update ),pending state ( Determine whether it is waiting , Avoid multiple executions ),flushCallbacks() function ( Deposit callbacks Execute all the contents in ),timerFunc() function ( According to the browser Promise、MutationObserver、setImmediate and setTimeout Support for , Defined as different content ),nextTick() function ( Go to callbacks Add callback content to , And call timerFunc Execute the corresponding callback ). The key source code is as follows :

  var callbacks = [];
  var pending = false;
  var timerFunc;
  
  function flushCallbacks () {
    pending = false;
    var copies = callbacks.slice(0);
    callbacks.length = 0;
    for (var i = 0; i < copies.length; i++) {
      copies[i]();
    }
  }
  
  if (typeof Promise !== 'undefined' && isNative(Promise)) {
    var p = Promise.resolve();
    timerFunc = function () {
      p.then(flushCallbacks);
      if (isIOS) { setTimeout(noop); }
    };
    isUsingMicroTask = true;
  } else if (!isIE && typeof MutationObserver !== 'undefined' && (
    isNative(MutationObserver) ||
    MutationObserver.toString() === '[object MutationObserverConstructor]'
  )) {
    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)) {
    timerFunc = function () {
      setImmediate(flushCallbacks);
    };
  } else {
    timerFunc = function () {
      setTimeout(flushCallbacks, 0);
    };
  }
  
  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();
    }
    if (!cb && typeof Promise !== 'undefined') {
      return new Promise(function (resolve) {
        _resolve = resolve;
      })
    }
  }
 Copy code 
Execution steps :
  • call nextTick (cb, ctx) function , towards callbacks Add the corresponding callback in
  • Judge the present pending Whether it is false, If so , Change it to true, At the same time call timerFunc() function ( The function is Promise、MutationObserver、setImmediate、setTimeout Which of these , See whether the browser supports this method in the code to judge , It involves isIOS、isIE、isNative Equal functions are in vue In principle, it has been encapsulated )
  • When cb When there is no , Return to one Promise function
  • perform flushCallbacks(), Execute add to callbacks The function in ( here dom Has been updated )
Method recommendation :

It is recommended to make a demo, hold vue Download the source code , stay nextTick() In the middle debugger, Single step debugging , View the source code running process .

版权声明
本文为[Hee hee 981]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/09/20210909131415436L.html

Scroll to Top