vue中ref引用操作DOM元素的實(shí)現(xiàn)
前言
在javascript中,我們用原生的方式獲取頁(yè)面中的DOM元素,并操作它們。后來(lái),有了jquery,jquery的強(qiáng)大就在于它可以很方便的操作DOM元素。
在vue中,如何操作DOM元素呢?
首先,在vue中強(qiáng)烈禁用原生與jquery來(lái)操作DOM元素。我們要充分的利用vue的優(yōu)勢(shì):MVVM,在vue中程序員幾乎不操作DOM,只需要維護(hù)好數(shù)據(jù)即可,vue給程序員提供ref引用,不調(diào)用api直接獲取元素組件的使用
一,$refs對(duì)象介紹及基本用法
refs對(duì)象的介紹:在每個(gè)vue的組件實(shí)例上,都包含一個(gè) r e f 對(duì)象 = = 存儲(chǔ)著對(duì)應(yīng)的 = = D O M 元素 = = 或 = = 組件 = = 的引用, = = 默認(rèn)情況下,組件的 ref對(duì)象==存儲(chǔ)著對(duì)應(yīng)的==DOM元素==或==組件==的引用,==默認(rèn)情況下,組件的 ref對(duì)象==存儲(chǔ)著對(duì)應(yīng)的==DOM元素==或==組件==的引用,==默認(rèn)情況下,組件的refs指向一個(gè)空對(duì)象,凡是以$開(kāi)頭的,都是vue的內(nèi)置對(duì)象

基礎(chǔ)使用方法(獲取DOM元素):比如我們要獲取h1,則我們給它取一個(gè)名字并放入ref中,代碼如下:
<h1 ref="myh1">App 根組件</h1>
在引用時(shí),只需在js中:
this.$refs.myh1.style.color = "red";
既可以成功操作:

我們來(lái)看看現(xiàn)在的refs中是不是多了myh1這一個(gè)成員:

總結(jié)一下:vue中有一個(gè)$refs對(duì)象,默認(rèn)為空。當(dāng)我們?cè)贒OM元素中為其設(shè)置ref值后,相當(dāng)于在vue的內(nèi)置對(duì)象 $refs中添加了新的成員,我們?nèi)绻枰僮鱀OM對(duì)象直接通過(guò) $refs獲取即可。
二,使用ref引用組件實(shí)例
ref除了可以引入DOM元素,還可以引入組件??梢阅玫浇M件并操控里面的方法與數(shù)據(jù)
大家請(qǐng)看left組件結(jié)構(gòu)
<template>
<div class="left-container">
<h3>left組件------{{ count }}</h3>
<button @click="count += 1">+1</button>
<button @click="resetCount">重置</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
resetCount() {
this.count = 0;
}
}
}
</script>
<style>
.left-container {
height: 200px;
background-color: orange;
}
</style>
在我將Left組件導(dǎo)入到App.vue后,我想在App組件中操作Left組件中的元素,比如,我想重置Left組件的count值為0:
首先,與操作DOM元素一樣,我要先給Left組件一個(gè)ref值:
<Left ref="comLeft"></Left>
在添加ref后,我們?cè)偃ビ^察$refs,多了成員comLeft:

接著,我再設(shè)置一個(gè)按鈕,要求按鈕按下后,重置Left組件中的count值為0:
<button @click="onReset">重置Left組件的count值為0</button>
然后設(shè)置onReset函數(shù):(用到$refs中的comLeft)
onReset() {
this.$refs.comLeft.resetCount();
}
三,ref的使用案例
3.1 案例需求
案例需求:實(shí)現(xiàn)按鈕和文本框的按需展示:
有輸入框->看不到按鈕;
有按鈕->看不到輸入框。
3.2 思路與做法
首先寫(xiě)出結(jié)構(gòu),一個(gè)輸入框與一個(gè)按鈕。點(diǎn)擊按鈕時(shí),按鈕消失,輸入框失去焦點(diǎn),輸入框消失:
通過(guò)上述分析,我們可以知道大的方向是要有一個(gè)布爾值,默認(rèn)如果布爾值為false,則默認(rèn)展示按鈕隱藏輸入框,否則(true)展示輸入框隱藏按鈕。
需要用到的知識(shí):
用@click=“”綁定點(diǎn)擊事件;v-if與v-show控制元素是否顯示(動(dòng)態(tài)的添加與刪除元素);使用ref綁定輸入框,并使用輸入框的focus來(lái)控制輸入框的焦點(diǎn)。
代碼如下:
<!-- 小demo -->
<input type="text" v-if="inputVisible" @blur="showButton" ref="iptRef"/>
<button v-else @click="showInput">展示輸入框</button>
data() {
return {
//控制輸入框和按鈕的按需切換,默認(rèn)值為false表示默認(rèn)展示按鈕隱藏輸入框
inputVisible: false
}
},
methods: {
showThis() {
console.log(this);
console.log(this.$refs.myh1);
console.log(this.$refs.comLeft);
this.$refs.myh1.style.color = "red";
},
onReset() {
console.log(this.$refs);
this.$refs.comLeft.resetCount();
},
showInput() {
//切換布爾值,把文本框展示出來(lái)
this.inputVisible = true;
//讓展示出來(lái)的文本框自動(dòng)獲取焦點(diǎn)
this.$refs.iptRef.focus();
},
showButton() {
this.inputVisible = false;
}
},
請(qǐng)自行編譯上述代碼會(huì)發(fā)現(xiàn)問(wèn)題:雖然showInput提供方法讓展示出來(lái)的文本框自動(dòng)獲得焦點(diǎn),但是在頁(yè)面中卻無(wú)法實(shí)現(xiàn)。
3.2 為什么頁(yè)面上無(wú)法自動(dòng)獲得焦點(diǎn)
因?yàn)楫?dāng)布爾值變成true的時(shí)候,頁(yè)面還沒(méi)來(lái)得及更新,這里就跟聲明周期有關(guān)系了,js是單線程,從上往下渲染,布爾值變成true,還是一個(gè)將要展示,還沒(méi)有展示的狀態(tài),所以在頁(yè)面中渲染不出來(lái):

解決方法是:保證頁(yè)面先更新完再執(zhí)行這個(gè)操作,延遲this.$refs.iptRef.focus()的使用在這里插入代碼片
如何延遲?我們能不能把這個(gè)操作放在updated中?==答案是不能,因?yàn)橛|發(fā)updated的條件是,只要數(shù)據(jù)發(fā)生變化就可以觸發(fā)。所以,當(dāng)this.inputVisible發(fā)生變化,就會(huì)觸發(fā)事件。(updated:數(shù)據(jù)更新后,完成虛擬DOM的重新渲染和打補(bǔ)丁。組件DOM已完成更新,可執(zhí)行依賴的DOM操作。注意:不要在此函數(shù)中操作數(shù)據(jù)(修改屬性),會(huì)陷入死循環(huán))
那么,有什么更好的解決方法呢?
3.3 this.$nextTick(cb)
組件的this.$nextTick(cb)方法,會(huì)把cb回調(diào)推遲到下一個(gè)DOM更新周期之后執(zhí)行
理解:等組件DOM更新完成后,再執(zhí)行cb回調(diào)函數(shù),從而保證cb回調(diào)可操作最新的DOM元素
用法:在括號(hào)中(cb回調(diào)函數(shù))放入箭頭函數(shù)并執(zhí)行操作
showInput() {
//切換布爾值,把文本框展示出來(lái)
this.inputVisible = true;
//讓展示出來(lái)的文本框自動(dòng)獲取焦點(diǎn)
// this.$refs.iptRef.focus();
this.$nextTick(() => {
this.$refs.iptRef.focus();
})
}
3.4 整體代碼
<template>
<div class="app-container">
<h1 ref="myh1">App 根組件</h1>
<button @click="showThis">打印 this</button>
<button @click="onReset">重置Left組件的count值為0</button>
<hr />
<!-- 小demo -->
<input type="text" v-if="inputVisible" @blur="showButton" ref="iptRef"/>
<button v-else @click="showInput">展示輸入框</button>
<!-- 渲染Left組件 -->
<div class="box">
<Left ref="comLeft"></Left>
</div>
</div>
</template>
<script>
import Left from "./components/Left.vue";
// console.log($refs);
export default {
data() {
return {
//控制輸入框和按鈕的按需切換,默認(rèn)值為false表示默認(rèn)展示按鈕隱藏輸入框
inputVisible: false
}
},
methods: {
showThis() {
console.log(this);
console.log(this.$refs.myh1);
console.log(this.$refs.comLeft);
this.$refs.myh1.style.color = "red";
},
onReset() {
console.log(this.$refs);
this.$refs.comLeft.resetCount();
},
showInput() {
//切換布爾值,把文本框展示出來(lái)
this.inputVisible = true;
//讓展示出來(lái)的文本框自動(dòng)獲取焦點(diǎn)
// this.$refs.iptRef.focus();
this.$nextTick(() => {
this.$refs.iptRef.focus();
})
},
showButton() {
this.inputVisible = false;
}
},
components: {
Left,
},
// updated() {
// this.$refs.iptRef.focus();
// }錯(cuò)誤,只要數(shù)據(jù)變化,就會(huì)觸發(fā)updated
};
</script>
<style>
</style>
四,總結(jié)
看完這節(jié)知識(shí)相信已經(jīng)學(xué)會(huì)了如何操作頁(yè)面中的DOM元素與組件,并知曉了在頁(yè)面DOM元素更新完后如何操作元素的方法與原理。
到此這篇關(guān)于vue中ref引用操作DOM元素的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue ref引用操作DOM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot之springboot與netty整合方案
這篇文章主要介紹了VUE之關(guān)于store狀態(tài)管理核心解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
Vue 實(shí)現(xiàn)把表單form數(shù)據(jù) 轉(zhuǎn)化成json格式的數(shù)據(jù)
今天小編就為大家分享一篇Vue 實(shí)現(xiàn)把表單form數(shù)據(jù) 轉(zhuǎn)化成json格式的數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10
vue3中頁(yè)面跳轉(zhuǎn)兩種實(shí)現(xiàn)方式
在Vue3中Vue?Router是一個(gè)常用的路由管理庫(kù),它提供了一種簡(jiǎn)單而強(qiáng)大的方式來(lái)實(shí)現(xiàn)路由跳轉(zhuǎn)和導(dǎo)航,這篇文章主要給大家介紹了關(guān)于vue3中頁(yè)面跳轉(zhuǎn)的兩種實(shí)現(xiàn)方式,需要的朋友可以參考下2024-09-09
解決element ui el-row el-col里面高度不一致問(wèn)題
這篇文章主要介紹了解決element ui el-row el-col里面高度不一致問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
vue+spring boot實(shí)現(xiàn)校驗(yàn)碼功能
這篇文章主要為大家詳細(xì)介紹了vue+spring boot實(shí)現(xiàn)校驗(yàn)碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
vue實(shí)現(xiàn)動(dòng)態(tài)路由的方法及路由原理解析
這篇文章主要介紹了路由原理及vue實(shí)現(xiàn)動(dòng)態(tài)路由,Vue Router 提供了豐富的 API,可以輕松地實(shí)現(xiàn)路由功能,并支持路由參數(shù)、查詢參數(shù)、命名路由、嵌套路由等功能,可以滿足不同應(yīng)用程序的需求,需要的朋友可以參考下2023-06-06

