Why nextTick

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>example</title> </head> <body> <div id="app"> <div V-if ="isShow"> <input type="text" ref="userName" /> </div> <button @click="showInput"> </html> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { isShow: false }, methods:{ showInput(){ this.isShow = true this.$refs.userName.focus() } } }) </script>Copy the code

The result is an error, the node could not be found. In other words, when you reach isShow=true, the DOM node has not yet been updated and you have to wait for the DOM to be updated before you can perform focus.

With a MessageChannel implementation

<! DOCTYPE html> <html lang="en-zh"> <head> <meta charset="utf-8" /> <style type="text/css"> </style> </head> <body> <div Id ="app"> <div v-if="isShow"> <input type="text" ref="userName" /> </div> </body> </html> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({  el: '#app', data: { isShow: false }, methods: { showInput(){ this.isShow = true; this.myNextTick(() => { this.$refs.userName.focus(); }) }, myNextTick(fanc){ var that = this; const ch = new MessageChannel(); const port1 = ch.port1; const port2 = ch.port2; port2.onmessage = (() => { fanc(); }) port1.postMessage(1); } } }) </script>Copy the code

Use MutationObserver implementation

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>example</title> </head> <body> <div id="app"> <div V-if ="isShow"> <input type="text" ref="userName" /> </div> <button @click="showInput"> </html> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el: '#app', data: { isShow: false }, methods:{ showInput(){ this.isShow = true this.mynextTick(()=>{ this.$refs.userName.focus() }) }, MynextTick (func){var textNode = document.createTextNode(0) var that = this var callback = function(mutationsList, observer) { func.call(that); / / or / / fanc (); } var observer = new MutationObserver(callback); Observe.observe.observe (textNode,{characterData:true}) TextNode. data = 1Copy the code

Why deprecate MessageChannel and use MutationObserver

Vue2 replaced MessageChannel with MutationObser on December 20, 2018 (many blogs say the opposite, but git timeline looks like this).

Because MutationObserver is a macro task and MessageChannel is a micro task, it must have been chosen for this reason.

<! DOCTYPE html> <html lang="en-zh"> <head> <meta charset="utf-8" /> <style type="text/css"> </style> </head> <body> <div Id ="app"> <div v-if="isShow"> <input type="text" ref="userName" /> </div> </body> </html> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({  el: '#app', data: { isShow: false }, methods: { showInput(){ this.isShow = true; this.myNextTick1(() => { this.$refs.userName.focus(); }) this.myNextTick2(() => { this.$refs.userName.focus(); }) }, myNextTick1(fanc){ var that = this; const ch = new MessageChannel(); const port1 = ch.port1; const port2 = ch.port2; port2.onmessage = (() => { console.log('1') fanc(); }) port1.postMessage(1); }, myNextTick2 (fanc) { var that = this; var textNode = document.createTextNode('0'); var callback = function(mutationList, observer){ console.log('2') fanc(); } var observer = new MutationObserver(callback); observer.observe(textNode, {characterData: true}); textNode.data = 1; } } }) </script>Copy the code

Print it out:

2
1
Copy the code

Instead of executing them sequentially, the macro task MutationObserver is followed by the micro task MessageChannel.