- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > web開(kāi)發(fā) > JavaScript >
- 讓你一看就明白的$nextTick講解
今天我們要實(shí)現這個(gè)一個(gè)小功能;頁(yè)面渲染完成后展示一個(gè)div元素;當點(diǎn)擊這個(gè)div元素后;div元素消失;出現一個(gè)input元素;并且input元素聚焦,想必大家覺(jué)得簡(jiǎn)單,我們一起來(lái)看看~
創(chuàng )建一個(gè)組件,組件名稱(chēng)NextTick.vue;
在頁(yè)面中引入注冊
<template> <div> <next-tick></next-tick> </div> </template> <script lang="ts"> import NextTick from "../components/NextTick.vue" export default { name:"About", components:{ NextTick }, } </script>
<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>
this.flag=false; this.$refs.inputRef.focus();
當執行頁(yè)面操作的時(shí)候,this.$refs.inputRef.focus();
是需要消耗時(shí)間的(還沒(méi)有還得及刷新;還是舊的頁(yè)面)
此時(shí)還沒(méi)有獲取到dom元素。
所以會(huì )報錯。
解決方式1:
因此只要讓頁(yè)面能夠獲取元素就行;使用setTimeout
setTimeout(()=>{ this.$refs.inputRef.focus(); },100)
這樣來(lái)處理這個(gè)問(wèn)題,是可以的;
但是顯得非常的不專(zhuān)業(yè);
解決方式2:
//當組件根據最新的data數據,重新在視圖上完成渲染后,在執行里面的函調函數 this.$nextTick(()=>{ this.$refs.inputRef.focus(); })
有人說(shuō):因為v-if是動(dòng)態(tài)創(chuàng )建和銷(xiāo)毀;在創(chuàng )建和銷(xiāo)毀的過(guò)程中,是需要時(shí)間的!所以才會(huì )使用v-if獲取不到元素節點(diǎn),用v-show就可以避免。
感覺(jué)說(shuō)的有點(diǎn)道理?
我們嘗試一下將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>
我們發(fā)現雖然是頁(yè)面沒(méi)有報錯,但是還沒(méi)有聚焦;改為v-show明顯也不能夠解決這個(gè)問(wèn)題
之所以會(huì )出現這個(gè)問(wèn)題,是因為子組件中將this.flag=false后,立刻去執行了下面的代碼
this.$refs.inputRef.focus();
而在執行的時(shí)候,視圖還沒(méi)沒(méi)有來(lái)得及刷新;還是舊的頁(yè)面,此時(shí)還不能夠獲取到dom元素,因此出現了undefined;也就是為什么我們加上延時(shí)后就可以聚焦了;
當組件根據最新的data數據,重新在視圖上完成渲染后,在執行里面的函調函數
這就是$nextTick的基本用法
this.$nextTick(()=>{ this.$refs.inputRef.focus(); })
又有人說(shuō):因為是子組件,子組件比父組件后渲染。所以沒(méi)有獲取到元素節點(diǎn)。
這也是理由....
感覺(jué)還沒(méi)有上一個(gè)小伙伴說(shuō)的對,為了解決疑惑。我們決定將子組件變成頁(yè)面在看看
<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; this.$refs.inputRef.focus(); }, }, } </script>
我們發(fā)現仍然不可以;這就充分說(shuō)明了:更新data的數據后,vue并不是實(shí)時(shí)更新的。
數據更新到顯示到頁(yè)面有時(shí)間差,我們在時(shí)間差內調用頁(yè)面數據,當然獲取不到。
也就是說(shuō):Vue在更新 DOM 時(shí)是異步執行的
之所以會(huì )有$nextTick;因為在vue中數據發(fā)生變化后;視圖上的dom并不會(huì )立刻去跟新;dom的跟新是需要時(shí)間的
下面我們通過(guò)一個(gè)小實(shí)驗來(lái)看一下
<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>
我們發(fā)現,第一次的值和第二次的值,是不一樣的;因為視圖上dom的跟新是需要之間的;我們在這個(gè)之間差內去獲取元素值;仍然是舊值;所以第一次的值是最初的值;第二次的值才是改變后的值;
由于我們希望跟新數據后,仍然可以立刻獲取dom上的值
所以vue提供了$nextTick就可以解決這個(gè)問(wèn)題
Vue.nextTick是全局方法
this.$nextTick( [callback] ) 是實(shí)例方法。
我們都知道一個(gè)頁(yè)面可以有多個(gè)實(shí)例,也就是說(shuō)this.$nextTick可以精確到某個(gè)實(shí)例上。其實(shí)本質(zhì)上兩個(gè)是一樣的。
只是一個(gè)是全局,一個(gè)是精確到某一個(gè)實(shí)例。精確度不一樣而已。
我們都知道在生命周期mounted渲染的時(shí)候,不能百分百保證所有的子組件都能夠被渲染,因此我們可以在mounted里面使用 this.$nextTick,這樣就能保證所有的子組件都能被渲染到。
mounted鉤子在服務(wù)器端渲染期間不被調用。
mounted: function () { this.$nextTick(function () { //在數據發(fā)生變化, //重新在視圖上完成渲染后,在執行里面的方法 //這一句話(huà)等同與: //將回調延遲到下次 DOM 更新循環(huán)之后執行 //等同于:在修改數據之后,然后等待 DOM 更新后在執行 }) }
到此這篇關(guān)于$nextTick的文章就介紹到這了,更多相關(guān)$nextTick講解內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站