vue中ref引用操作DOM元素的實(shí)現(xiàn)
前言
在javascript中,我們用原生的方式獲取頁面中的DOM元素,并操作它們。后來,有了jquery,jquery的強(qiáng)大就在于它可以很方便的操作DOM元素。
在vue中,如何操作DOM元素呢?
首先,在vue中強(qiáng)烈禁用原生與jquery來操作DOM元素。我們要充分的利用vue的優(yōu)勢:MVVM,在vue中程序員幾乎不操作DOM,只需要維護(hù)好數(shù)據(jù)即可,vue給程序員提供ref引用,不調(diào)用api直接獲取元素組件的使用
一,$refs對象介紹及基本用法
refs對象的介紹:在每個(gè)vue的組件實(shí)例上,都包含一個(gè) r e f 對象 = = 存儲著對應(yīng)的 = = D O M 元素 = = 或 = = 組件 = = 的引用, = = 默認(rèn)情況下,組件的 ref對象==存儲著對應(yīng)的==DOM元素==或==組件==的引用,==默認(rèn)情況下,組件的 ref對象==存儲著對應(yīng)的==DOM元素==或==組件==的引用,==默認(rèn)情況下,組件的refs指向一個(gè)空對象,凡是以$開頭的,都是vue的內(nèi)置對象
基礎(chǔ)使用方法(獲取DOM元素):比如我們要獲取h1,則我們給它取一個(gè)名字并放入ref中,代碼如下:
<h1 ref="myh1">App 根組件</h1>
在引用時(shí),只需在js中:
this.$refs.myh1.style.color = "red";
既可以成功操作:
我們來看看現(xiàn)在的refs中是不是多了myh1這一個(gè)成員:
總結(jié)一下:vue中有一個(gè)$refs對象,默認(rèn)為空。當(dāng)我們在DOM元素中為其設(shè)置ref值后,相當(dāng)于在vue的內(nèi)置對象 $refs中添加了新的成員,我們?nèi)绻枰僮鱀OM對象直接通過 $refs獲取即可。
二,使用ref引用組件實(shí)例
ref除了可以引入DOM元素,還可以引入組件。可以拿到組件并操控里面的方法與數(shù)據(jù)
大家請看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后,我們再去觀察$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 思路與做法
首先寫出結(jié)構(gòu),一個(gè)輸入框與一個(gè)按鈕。點(diǎn)擊按鈕時(shí),按鈕消失,輸入框失去焦點(diǎn),輸入框消失:
通過上述分析,我們可以知道大的方向是要有一個(gè)布爾值,默認(rèn)如果布爾值為false,則默認(rèn)展示按鈕隱藏輸入框,否則(true)展示輸入框隱藏按鈕。
需要用到的知識:
用@click=“”綁定點(diǎn)擊事件;v-if與v-show控制元素是否顯示(動(dòng)態(tài)的添加與刪除元素);使用ref綁定輸入框,并使用輸入框的focus來控制輸入框的焦點(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() { //切換布爾值,把文本框展示出來 this.inputVisible = true; //讓展示出來的文本框自動(dòng)獲取焦點(diǎn) this.$refs.iptRef.focus(); }, showButton() { this.inputVisible = false; } },
請自行編譯上述代碼會發(fā)現(xiàn)問題:雖然showInput提供方法讓展示出來的文本框自動(dòng)獲得焦點(diǎn),但是在頁面中卻無法實(shí)現(xiàn)。
3.2 為什么頁面上無法自動(dòng)獲得焦點(diǎn)
因?yàn)楫?dāng)布爾值變成true的時(shí)候,頁面還沒來得及更新,這里就跟聲明周期有關(guān)系了,js是單線程,從上往下渲染,布爾值變成true,還是一個(gè)將要展示,還沒有展示的狀態(tài),所以在頁面中渲染不出來:
解決方法是:保證頁面先更新完再執(zhí)行這個(gè)操作,延遲this.$refs.iptRef.focus()的使用在這里插入代碼片
如何延遲?我們能不能把這個(gè)操作放在updated中?==答案是不能,因?yàn)橛|發(fā)updated的條件是,只要數(shù)據(jù)發(fā)生變化就可以觸發(fā)。所以,當(dāng)this.inputVisible發(fā)生變化,就會觸發(fā)事件。(updated:數(shù)據(jù)更新后,完成虛擬DOM的重新渲染和打補(bǔ)丁。組件DOM已完成更新,可執(zhí)行依賴的DOM操作。注意:不要在此函數(shù)中操作數(shù)據(jù)(修改屬性),會陷入死循環(huán))
那么,有什么更好的解決方法呢?
3.3 this.$nextTick(cb)
組件的this.$nextTick(cb)方法,會把cb回調(diào)推遲到下一個(gè)DOM更新周期之后執(zhí)行
理解:等組件DOM更新完成后,再執(zhí)行cb回調(diào)函數(shù),從而保證cb回調(diào)可操作最新的DOM元素
用法:在括號中(cb回調(diào)函數(shù))放入箭頭函數(shù)并執(zhí)行操作
showInput() { //切換布爾值,把文本框展示出來 this.inputVisible = true; //讓展示出來的文本框自動(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() { //切換布爾值,把文本框展示出來 this.inputVisible = true; //讓展示出來的文本框自動(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ù)變化,就會觸發(fā)updated }; </script> <style> </style>
四,總結(jié)
看完這節(jié)知識相信已經(jīng)學(xué)會了如何操作頁面中的DOM元素與組件,并知曉了在頁面DOM元素更新完后如何操作元素的方法與原理。
到此這篇關(guān)于vue中ref引用操作DOM元素的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue ref引用操作DOM內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot之springboot與netty整合方案
這篇文章主要介紹了VUE之關(guān)于store狀態(tài)管理核心解析,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Vue 實(shí)現(xiàn)把表單form數(shù)據(jù) 轉(zhuǎn)化成json格式的數(shù)據(jù)
今天小編就為大家分享一篇Vue 實(shí)現(xiàn)把表單form數(shù)據(jù) 轉(zhuǎn)化成json格式的數(shù)據(jù),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10vue3中頁面跳轉(zhuǎn)兩種實(shí)現(xiàn)方式
在Vue3中Vue?Router是一個(gè)常用的路由管理庫,它提供了一種簡單而強(qiáng)大的方式來實(shí)現(xiàn)路由跳轉(zhuǎn)和導(dǎo)航,這篇文章主要給大家介紹了關(guān)于vue3中頁面跳轉(zhuǎn)的兩種實(shí)現(xiàn)方式,需要的朋友可以參考下2024-09-09解決element ui el-row el-col里面高度不一致問題
這篇文章主要介紹了解決element ui el-row el-col里面高度不一致問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08vue+spring boot實(shí)現(xiàn)校驗(yàn)碼功能
這篇文章主要為大家詳細(xì)介紹了vue+spring boot實(shí)現(xiàn)校驗(yàn)碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05vue實(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