Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the asynchronism of Vue.nextTick in Vue

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces "how to realize the asynchronism of Vue.nextTick in Vue". In the daily operation, I believe that many people have doubts about how to realize the asynchronism of Vue.nextTick in Vue. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubt of "how to realize the asynchronism of Vue.nextTick in Vue". Next, please follow the editor to study!

1. NextTick Quick Test

Do you really know nextTick? Come on, let's get to the point.

{{name}}

Modify name export default {name: 'App', data () {return {name:' Jing Bairan'}}, mounted () {console.log ('mounted', this.$refs.name.innerText)}, methods: {handleClick () {this.$nextTick (() = > console.log (' nextTick1', this.$refs.name.innerText)) this.name = 'jngboran' console.log (' sync log') This.$refs.name.innerText) this.$nextTick (() = > console.log ('nextTick2', this.$refs.name.innerText))}

In the above code, when you click the button "modify name", what will be output of the this.$refs.name.innerText corresponding to 'nextTick1','sync log','nextTick2'? Note that the innerText~ of DOM is printed here (the answer will be posted at the end of the article)

If you have a very firm answer at this time, you don't have to look down, but if you have concerns about your answer, you might as well follow me and move on. I believe that you do not need to see the answer can have a positive answer ~!

Second, nextTick source code implementation

The source code is located in core/util/next-tick. It can be divided into four parts, directly on the code.

1. Global variable

Callbacks queues, pending statu

Const callbacks = [] / / queue where cb is stored let pending = false / / whether to traverse the queue immediately and execute the flag 2. FlushCallbacks of cb

Traversing the callbacks executes each cb

Function flushCallbacks () {pending = false / / Note here, once executed, pending is immediately reset to false const copies = callbacks.slice (0) callbacks.length = 0 for (let I = 0; I

< copies.length; i++) { copies[i]() // 执行每个cb }}3. nextTick的异步实现 根据执行环境的支持程度采用不同的异步实现策略 let timerFunc // nextTick异步实现fnif (typeof Promise !== 'undefined' && isNative(Promise)) { // Promise方案 const p = Promise.resolve() timerFunc = () =>

{p.then (flushCallbacks) / / package flushCallbacks into Promise.then} isUsingMicroTask = true} else if (! isIE & & typeof MutationObserver! = 'undefined' & & (isNative (MutationObserver) | | MutationObserver.toString () =' [object MutationObserverConstructor]') {/ / MutationObserver scenario let counter = 1 const observer = new MutationObserver (flushCallbacks) / / cb const textNode = document.createTextNode (String (counter)) / / using flushCallbacks as the observed change Build text node / / observe text node changes observer.observe (textNode {characterData: true}) / / timerFunc changes the data of the text node The callback flushCallbacks timerFunc = () = > {counter = (counter + 1)% 2 textNode.data = String (counter)} isUsingMicroTask = true} else if (typeof setImmediate! = = 'undefined' & & isNative (setImmediate)) {/ / setImmediate scenario timerFunc = () = > {setImmediate (flushCallbacks)}} else {/ / final degradation scheme setTimeout timerFunc = () = > {setTimeout (flushCallbacks, 0)}}

Here is a real case to deepen our understanding of MutationObserver. After all, compared with the other three asynchronous schemes, this should be the strangest one.

Const observer = new MutationObserver (() = > console.log ('text node change observed') const textNode = document.createTextNode (String (1)) observer.observe (textNode, {characterData: true}) console.log ('script start') setTimeout (() = > console.log (' timeout1')) textNode.data = String (2) / / here the text node value is modified console.log ('script end')

Do you know what the corresponding output will be like?

Script start and script end will be executed in the first round of macro tasks, which is no problem.

SetTimeout will be put into the next round of macro task execution.

MutationObserver is a micro task, so it will be executed after this round of macro tasks, so it precedes setTimeout

The result is as follows:

4. NextTick method implementation

Cb, Promise mode

Export function nextTick (cb?: Function, ctx?: Object) {let _ resolve / / add cb callbacks.push (()) > {if (cb) {try {cb.call (ctx)} catch (e) {handleError (e, ctx) to the global callbacks queue 'nextTick')} else if (_ resolve) {/ / here is the Promise-supported writing _ resolve (ctx)}}) if (! pending) {pending = true / / execute timerFunc Execute all the cb timerFunc ()} / / a pair of Promise implementations in callbacks in the next Tick, which is why we can write nextTick.then when using if (! cb & & typeof Promise! = = 'undefined') {return new Promise (resolve = > {_ resolve = resolve})}}

Go deep into the details, what is the use of understanding pending, and how does it work?

Case 1, executing $nextTick,timerFunc twice in the same round of Tick will only be executed once.

This.$nextTick (() = > console.log ('nextTick1')) this.$nextTick () = > console.log (' nextTick2'))

Is it more intuitive to look at it with a picture?

III. Asynchronous updates of Vue components

If there are friends here who are not very familiar with Vue componentization and dispatching updates, you can poke here first, take a look at the schematic principle of Vue response, understand the related contents of Vue componentization and dispatching updates, and then come back to see.

In fact, the asynchronous update DOM of Vue is also implemented using nextTick, which is actually the same as the $nextTick we usually use.

Here we review, what happens when we change the value of an attribute?

According to the process of dispatching updates in the figure above, let's start with the opening of watcher.update, take rendering Watcher as an example, and enter into queueWatcher

1. What did queueWatcher do? / / the queue used to store Wathcer. Be careful not to be confused with nextTick's callbacks, they are all queues, but the usefulness is different ~ const queue: Array = [] function queueWatcher (watcher: Watcher) {const id = watcher.id / / get the id of Wathcer, this id has each watcher and is globally unique if (has [id] = = null) {/ / avoid adding duplicate wathcer This is also the optimization practice of asynchronous rendering has [id] = true if (! flushing) {queue.push (watcher)} if (! waiting) {waiting = true / / here push flushSchedulerQueue into nextTick's callbacks queue nextTick (flushSchedulerQueue)}} 2. What did flushSchedulerQueue do? Function flushSchedulerQueue () {currentFlushTimestamp = getNow () flushing = true let watcher, id / / sort to ensure that the father is followed by the child to perform the update, and that the userWatcher queue.sort ((a, b) = > a.id-b.id) / / traverses all the Watcher that needs to be updated before rendering the for (index = 0; index)

< queue.length; index++) { watcher = queue[index] id = watcher.id has[id] = null // 真正执行派发更新,render ->

Update-> patch watcher.run ()}}

Finally, a diagram understands the asynchronous update process of the component

Fourth, return to the topic itself.

I believe that after the above analysis of the nextTick source code, we have unveiled its mystery. At this time, you must be able to firmly say the answer ~ do not say much, let's check together to see if it is what you think!

1. As shown in the picture, the innerText in mounted is the Chinese word for Jing Bairan.

2. the next step is to click the button and print the result as shown in the figure

Yes, the output is as follows. Are you surprised? )

Sync log Jing Beran

NextTick1 Jing Beran

NextTick2 jngboran

Here's a brief analysis of each output:

This.$nextTick (() = > console.log ('nextTick1', this.$refs.name.innerText)) this.name =' jngboran'console.log ('sync log', this.$refs.name.innerText) this.$nextTick (() = > console.log (' nextTick2', this.$refs.name.innerText))

Sync log: there is nothing more to say about this synchronous printing. I believe most of the questions about children's shoes are not here. If you are not clear about children's shoes, you can review EventLoop first. I won't repeat it here.

NextTick1: note that although it is placed in the callback of $nextTick and executed in the next tick, its position is before this.name = 'jngboran'. In other words, his cb will be queued before the flushSchedulerQueue of the App component, and when nextTick1 prints, the App component has not yet dispatched the update, so it still gets the old Dom value.

NextTick2 will not be carried out, so you can analyze it yourself. I believe that everyone should be the most sure about it. Isn't that how we usually get the updated DOM?

Finally, let's take a picture to deepen understanding.

At this point, the study on "how to realize the asynchronism of Vue.nextTick in Vue" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report