This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!

1. Function Description

Today we're going to implement this little feature; When the page is rendered, show a div element; When you click on this div element; The div element disappears; An input element appears; Create a component called NextTick. Vue; create a component called NextTick. Introduce registration in the pageCopy the code

2. The parent component

<template> <div> <next-tick></next-tick> </div> </template> <script lang="ts"> import NextTick from ".. /components/NextTick.vue" export default { name:"About", components:{ NextTick }, } </script>Copy the code

3. Sub-component nexttick.vue

< span style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 13px! Important; white-space: inherit! Important; ref="inputRef" class="yuelaing"/> </div> </template> <script> export default { data(){ return{ flag:true, } }, methods: { handerClick(){ this.flag=false; this.$refs.inputRef.focus(); }, }, } </script>Copy the code

4 Why undefined

this.flag=false; this.$refs.inputRef.focus(); When performing page operations, this.$refs.inputref.focus (); It takes time (not yet to refresh; Still the old page) at this point the DOM element has not been obtained. So you get an error. Solution 1: So just let the page get the element; Use setTimeout setTimeout(()=>{this.$refs.inputref.focus (); },100) it is ok to deal with the problem this way; But very unprofessional; $nextTick()=>{this.$refs.inputref.focus (); $refs.inputref.focus (); $refs.inputref.focus (); })Copy the code

5. Can I get focus by changing v-if to V-show?

Some people say: because V-IF is dynamically created and destroyed; In the process of creating and destroying, it takes time! That's why v-if can't get the element nodes and v-show can avoid that. Does that make sense? Let's try v-if instead of V-showCopy the code
< span style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 13px! Important; white-space: inherit! Important;" flag" ref="inputRef" class="yuelaing"/> </div> </template> <script> export default { data(){ return{ flag:true, } }, methods: { handerClick(){ this.flag=false; console.log( this.$refs.inputRef); this.$refs.inputRef.focus(); }, }, } </script>Copy the code

6. Actual results

We found that although there was no error in the page, there was no focus; $refs.inputref.focus (); $refs.inputref.focus (); $refs.inputref.focus (); At execution time, the view has not yet been refreshed; Again, the old page, you can't get the DOM element yet so undefined; That's why we add a delay to focus; This.$nextTick(()=>{this.$refs.inputref.focus (); $refs.inputref.focus (); })Copy the code

7. Can you get focus by turning components into pages?

Some people say: because it is a child component, the child component than the parent component after rendering. So the element node is not retrieved. This is also the reason.... I don't feel like the last one was right. We decided to turn the child component into a page to look atCopy the code
< span style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 13px! Important; white-space: inherit! Important;" flag" ref="inputRef" class="yuelaing"/> </div> </template> <script> export default { data(){ return{ flag:true, } }, methods: { handerClick(){ this.flag=false; this.$refs.inputRef.focus(); }, }, } </script>Copy the code
We found that we still couldn't; This makes it abundantly clear that vUE is not updated in real time after data is updated. There is a time difference between data update and page display, we call the page data within the time difference, of course, can not get. In other words: Vue executes asynchronously when updating the DOMCopy the code

8. Why is there $nextTick

$nextTick; Because when the data changes in vUE; The DOM on the view is not immediately updated; It's going to take time to get the DOM up to date and we're going to do a little experimentCopy the code
< template > < div > < div ref = "unique" > < h1 > {{cont}} < / h1 > < / div > < div class = "sun" @ click = "handerClick" > change value of < / div > < / div > </template> <script> export default {data(){return{cont:' I'm the default '}}, methods: {handerClick(){this.cont=' I changed the default '; console.log('1==>',this.$refs.unique.innerText); this.$nextTick(()=>{ console.log('2==>',this.$refs.unique.innerText); }) }, }, } </script>Copy the code

What we find is that the first value is not the same as the second value; Because the dom on the view is between new and needed; We're going to get the element values within this difference; It's still the old value; So the first value is the original value; The second value is the changed value; Vue provides $nextTick to solve this problem because we want to be able to get the value on the DOM immediately after we follow the new dataCopy the code

NextTick and this.$nextTick

NextTick is a global method. This.$nextTick([callback]) is an instance method. We all know that a page can have multiple instances, which means that this.$nextTick can be precise to one instance. It's essentially the same thing. Only one is global, one is accurate to a particular instance. The accuracy is different.Copy the code

10. A little trick to use nextTick

In mounted, this.$nextTick is not a 100% guarantee that all subcomponents will be rendered, so use this.$nextTick in mounted to ensure that all subcomponents will be rendered. Mounted hooks are not called during server-side rendering. mounted: Function () {this.nexttick (function () {this.nexttick (function () {this.nexttick (function () {$nextTick(); // Delay the callback until after the next DOM update loop // is equivalent to: after modifying the data, then waiting for the DOM update before executing})}Copy the code