讓你一看就明白的$nextTick講解
目錄
- 1.功能描述
- 2.父元件
- 3.子元件NextTick.
- 4為什麼是undefined
- 5.將v-pmjkQtif更改為v-show可以獲取焦點嗎?
- 6.實際結果
- 7.將元件變成頁面可以獲取焦點嗎?
- 8.為什麼會有$nextTick
- 9.Vue.nextTick和this.$nextTick差別
- 10.使用 nextTick的一個小技巧
- 總結
1.功能描述
今天我們要實現這個一個小功能;頁面渲染完成後展示一個div元素;當點選這個div元素後;div元素消失;出現一個input元素;並且input元素聚焦,想必大家覺得簡單,我們一起來看看~
建立一個元件,元件名稱NextTick.vue;
在頁面中引入註冊
2.父元件
<template> <div> <next-tick></next-tick> </div> </template> <script lang="ts"> import NextTick from "../components/NextTick.vue" export default { name:"About",components:{ NextTick },} </script>
3.子元件NextTick.vue
<template> <div> <div>我是元件</div> <div v-if="flag" class="sun" @click="handerClick">顯示input</div> <input v-else ref="inputRef" class="yuelaing"/> </div> </template> <script> export default { data(){ return{ flag:true,} },methods: { handerClick(){ this.flag=false; this.$refs.inputRef.focus(); },},} </script>
4為什麼是undefined
this.flag=false; this.$refs.inputRef.focus();
當執行頁面操作的時候,this.$refs.inputRef.focus();
是需要消耗時間的(還沒有還得及重新整理;還是舊的頁面)
此時還沒有獲取到dom元素。
所以會報錯。
解決方式1:
因此只要讓頁面能夠獲取元素就行;使用setTimeout
setTimeout(()=>{ this.$refs.inputRef.focus(); },100)
這樣來處理這個問題,是可以的;
但是顯得非常的不專業;
解決方式2:
//當元件根據最新的data資料,重新在檢視上完成渲染後,在執行裡面的函調函式 this.$nextTick(()=>{ this.$refs.inputRef.focus(); })
5.將v-if更改為v-show可以獲取焦點嗎?
有人說:因為v-if是動態建立和銷燬;在建立和銷燬的過程中,是需要時間的!所以才會使用v-if獲取不到元素節點,用v-show就可以避免。
感覺說的有點道理?
我們嘗試一下將v-if換成v-show
<template>
<div>
<div>我是元件</div>
<div v-show="flag" class="sun" @click="handerClick">顯示input</div>
<input v-show="!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>
6.實際結果
我們發現雖然是頁面沒有報錯,但是還沒有聚焦;改為v-show明顯也不能夠解決這個問題
之所以會出現這個問題,是因為子元件中將this.flag=false後,立刻去執行了下面的程式碼
this.$refs.inputRef.focus();
而在執行的時候,檢視還沒沒有來得及重新整理;還是舊的頁面,此時還不能夠獲取到dom元素,因此出現了undefined;也就是為什麼我們加上延時後就可以聚焦了;
當元件根據最新的data資料,重新在檢視上完成渲染後,在執行裡面的函調函式
這就是$nextTick的基本用法
this.$nextTick(()=>{ this.$refs.inputRef.focus(); })
7.將元件變成頁面可以獲取焦點嗎?
又有人說:因為是子元件,子元件比父元件後渲染。所以沒有獲取到元素節點。
這也是理由....
感覺還沒有上一個小夥伴說的對,為了解決疑惑。我們決定將子元件變成頁面在看看
<template> <div> <div>我是元件</div> <div v-show="flag" class="sun" @click="handerClick">顯示input</div> <input v-show="!flag" 程式設計客棧ref="inputRef" class="yuelaing"/> </div> </template> <script> export default { data(){ return{ flag:true,} },methods: { handerClick(){ www.cppcns.com this.flag=false; this.$refs.inputRef.focus(); },} </script>
我們發現仍然不可以;這就充分說明了:更新data的資料後,vue並不是實時更新的。
資料更新到顯示到頁面有時間差,我們在時間差內呼叫頁面資料,當然獲取不到。
也就是說:Vue在更新 DOM 時是非同步執行的
8.為什麼會有$nextTick
之所以會有$nextTick;因為在vue中資料發生變化後;檢視上的dom並不會立刻去跟新;dom的跟新是需要時間的
下面我們通過一個小實驗來看一下
<template> <div> <div ref="unique"> <h1>{{ cont }}</h1> </div> <div class="sun" @click="handerClick">改變值</div> </div> </template> <script> export default { data(){ return{ cont:'我是預設值' } },methods: { handerClick(){ this.cont='我改變了預設值'; console.log('1==>',this.$refs.unique.innerText); this.$nextTick(()=>{ console.log('2==>',this.$refs.unique.innerText); }) },} </script>
我們發現,第一次的值和第二次的值,是不一樣的;因為檢視上dom的跟新是需要之間的;我們在這個之間差內去獲取元素值;仍然是舊值;所以第一次的值是最初的值;第二次的值才是改變後的值;
由於我們希望跟新資料後,仍然可以立刻獲取dom上的值
所以vue提供了$nextTick就可以解決這個問題
9.Vue.nextTick和this.$nextTick差別
Vue.nextTick是全域性方法
this.$nextTick( [callback] ) 是例項方法。
我們都知道一個頁面可以有多個例項,也就是說this.$nextTick可以精確到某個例項上。其實本質上兩個是一樣的。
只是一個是全域性,一個是精確到某一個例項。精確度不一樣而已。
10.使用 nextTick的一個小技巧
我們都知道在生命週期mounted渲染的時候,不能百分百保證所有的子元件都能夠被渲染,因此我們可以在mounted裡面使用 this.$nextTick,這樣就能保證所有的子元件都能被渲染到。
mounted鉤子在伺服器端渲染期間不被呼叫。
mounted: function () { this.$nextTick(function () { //在資料發生變化, //重新在檢視上完成渲染後,在執行裡面的方法 //這一句話等同與: //將回調延遲到下次 DOM 更新迴圈之後執行 //等同於:在修改資料之後,然後等待 DOM 更新後在執行 }) }
總結
到此這篇關於$nextTick的文章就介紹到這了,更多相關$nextTick講解內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!