Vue 項目中使用$refs來訪問組件實例或 DOM 元素,有哪些注意事項?

大白話Vue 項目中使用$refs來訪問組件實例或 DOM 元素,有哪些注意事項?

在 Vue 項目里,$refs 是個超實用的工具,它能讓你直接訪問組件實例或者 DOM 元素。不過使用的時候,有一些地方可得注意,下面咱就詳細嘮嘮。

1. $refs 只有在組件渲染完成后才可用

在 Vue 里,組件從創建到渲染完成是有個過程的。只有當組件完全渲染好了,$refs 才能正常使用。要是在組件還沒渲染好的時候就想用 $refs 去訪問東西,那肯定會出問題。所以,通常會把使用 $refs 的代碼放到 mounted 鉤子函數里,因為這個鉤子函數是在組件渲染完成后才執行的。

export default {// 組件掛載完成后執行的鉤子函數mounted() {// 這里可以安全地使用 $refs 訪問組件實例或 DOM 元素this.$refs.myComponent.someMethod(); // 調用組件實例的方法this.$refs.myElement.focus(); // 讓 DOM 元素獲取焦點}
};

2. 不要在模板里直接使用 $refs

雖然 $refs 能讓你訪問組件實例或者 DOM 元素,但千萬別在模板里直接用它。因為模板里的代碼會在每次數據更新的時候重新計算,如果在模板里用 $refs,可能會導致意外的結果,而且還會影響性能。

<template><!-- 不要這樣做 --><!-- <div>{{ $refs.myElement.textContent }}</div> --><div ref="myElement">這是一個 DOM 元素</div>
</template><script>
export default {mounted() {// 在 mounted 鉤子函數里使用 $refsconst text = this.$refs.myElement.textContent;console.log(text); // 輸出: 這是一個 DOM 元素}
};
</script>

3. $refs 不是響應式的

$refs 不像 Vue 的響應式數據那樣,數據一變頁面就跟著更新。$refs 只是一個普通的對象,它的屬性值在組件渲染完成后就固定了。所以,如果你想在數據變化的時候更新 $refs 相關的操作,就得手動去處理。

<template><div><button @click="updateElement">更新元素</button><div ref="myElement">{{ message }}</div></div>
</template><script>
export default {data() {return {message: '初始消息'};},methods: {updateElement() {this.message = '更新后的消息';// 手動更新 $refs 相關的操作this.$refs.myElement.textContent = this.message;}}
};
</script>

4. 動態綁定 ref 時要注意

要是你需要動態綁定 ref,也就是根據不同的條件給不同的元素或者組件綁定 ref,那得小心了。因為動態綁定 ref 可能會導致 $refs 的值發生變化,所以在使用的時候要確保 $refs 里確實有你想要的元素或者組件。

<template><div><!-- 動態綁定 ref --><component :is="currentComponent" :ref="currentRef"></component><button @click="switchComponent">切換組件</button></div>
</template><script>
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';export default {data() {return {currentComponent: ComponentA,currentRef: 'componentRef',componentRef: null};},methods: {switchComponent() {this.currentComponent = this.currentComponent === ComponentA ? ComponentB : ComponentA;// 切換組件后,確保 $refs 里有正確的組件實例if (this.$refs.componentRef) {this.$refs.componentRef.someMethod();}}}
};
</script>

5. 在子組件銷毀時清理 $refs

當子組件被銷毀的時候,$refs 里對應的引用不會自動清除。所以,要是你在子組件銷毀后還去訪問 $refs 里的這個引用,就會報錯。為了避免這種情況,你可以在子組件銷毀的時候手動清理 $refs 里的引用。

<template><div><child-component ref="childRef"></child-component><button @click="destroyChild">銷毀子組件</button></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},methods: {destroyChild() {// 銷毀子組件this.$refs.childRef.$destroy();// 手動清理 $refs 里的引用this.$refs.childRef = null;}}
};
</script>

總之,$refs 是個很強大的工具,但使用的時候得注意上面這些點,這樣才能避免出現各種奇怪的問題,讓你的 Vue 項目更加穩定。

除了$refs,Vue還有哪些可以訪問組件實例或DOM元素的方式?

在 Vue 里,除了使用 $refs 訪問組件實例或 DOM 元素外,還有以下幾種方式:

1. 通過事件機制傳遞信息

在 Vue 中,你可以利用自定義事件和事件總線在組件間傳遞數據,從而間接訪問組件實例。

自定義事件

子組件能夠通過 $emit 觸發自定義事件,把數據傳遞給父組件,父組件在接收到事件后就可以訪問子組件實例的屬性或方法。

<template><!-- 父組件 --><div><child-component @custom-event="handleCustomEvent"></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},methods: {handleCustomEvent(childInstance) {// 訪問子組件實例console.log(childInstance.someMethod());}}
};
</script>
<template><!-- 子組件 --><div><button @click="sendInstance">發送實例</button></div>
</template><script>
export default {methods: {sendInstance() {// 觸發自定義事件,傳遞當前組件實例this.$emit('custom-event', this);},someMethod() {return '這是子組件的方法';}}
};
</script>
事件總線

事件總線是一個全局的事件中心,組件能夠在上面觸發和監聽事件,以此實現組件間的通信。

// eventBus.js
import Vue from 'vue';
export const eventBus = new Vue();
<template><!-- 發送組件 --><div><button @click="sendMessage">發送消息</button></div>
</template><script>
import { eventBus } from './eventBus.js';export default {methods: {sendMessage() {// 觸發事件總線的事件eventBus.$emit('message-sent', this);}}
};
</script>
<template><!-- 接收組件 --><div></div>
</template><script>
import { eventBus } from './eventBus.js';export default {mounted() {// 監聽事件總線的事件eventBus.$on('message-sent', (senderInstance) => {console.log(senderInstance.someMethod());});}
};
</script>

2. 使用 provideinject

provideinject 主要用于實現跨級組件間的通信,父組件能夠通過 provide 提供數據,子組件可以使用 inject 注入這些數據。

<template><!-- 父組件 --><div><child-component></child-component></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},provide() {return {parentInstance: this};}
};
</script>
<template><!-- 子組件 --><div></div>
</template><script>
export default {inject: ['parentInstance'],mounted() {// 訪問父組件實例console.log(this.parentInstance.someMethod());}
};
</script>

3. 使用 Vue.observable(Vue 2)或 reactive(Vue 3)

在 Vue 2 里可以使用 Vue.observable 創建一個響應式對象,在 Vue 3 中則使用 reactive。通過這個響應式對象存儲組件實例,從而實現對組件實例的訪問。

Vue 2
// store.js
import Vue from 'vue';export const store = Vue.observable({componentInstance: null
});
<template><!-- 組件 A --><div><button @click="setInstance">設置實例</button></div>
</template><script>
import { store } from './store.js';export default {methods: {setInstance() {// 將當前組件實例存儲到響應式對象中store.componentInstance = this;}}
};
</script>
<template><!-- 組件 B --><div></div>
</template><script>
import { store } from './store.js';export default {mounted() {// 訪問存儲的組件實例if (store.componentInstance) {console.log(store.componentInstance.someMethod());}}
};
</script>
Vue 3
// store.js
import { reactive } from 'vue';export const store = reactive({componentInstance: null
});
<template><!-- 組件 A --><div><button @click="setInstance">設置實例</button></div>
</template><script setup>
import { store } from './store.js';const setInstance = () => {// 將當前組件實例存儲到響應式對象中store.componentInstance = getCurrentInstance();
};
</script>
<template><!-- 組件 B --><div></div>
</template><script setup>
import { store } from './store.js';if (store.componentInstance) {console.log(store.componentInstance.someMethod());
}
</script>

這些方法都有各自的適用場景,你可以根據具體需求來選擇合適的方式。

在Vue中,如何避免$refs訪問帶來的性能問題?

在 Vue 里使用 $refs 訪問組件實例或 DOM 元素時,若使用不當可能會引發性能問題。以下是一些避免 $refs 訪問帶來性能問題的方法:

1. 避免在渲染循環中頻繁訪問 $refs

$refs 本身并非響應式的,但在渲染循環里頻繁訪問 $refs 會導致不必要的計算和 DOM 操作,從而降低性能。應該把 $refs 的訪問邏輯移到事件處理函數或者生命周期鉤子函數中。

<template><div><div ref="myElement">示例元素</div><button @click="handleClick">點擊</button></div>
</template><script>
export default {methods: {handleClick() {// 在事件處理函數中訪問 $refsconst element = this.$refs.myElement;if (element) {// 對元素進行操作element.style.color = 'red';}}}
};
</script>

2. 僅在必要時使用 $refs

$refs 主要用于直接訪問組件實例或 DOM 元素,不過很多時候可以借助 Vue 的響應式系統來實現相同的功能,從而避免使用 $refs

示例:動態改變樣式

不使用 $refs 的情況:

<template><div><div :style="{ color: textColor }">示例元素</div><button @click="changeColor">改變顏色</button></div>
</template><script>
export default {data() {return {textColor: 'black'};},methods: {changeColor() {this.textColor = 'red';}}
};
</script>

3. 及時清理不再使用的 $refs

當組件被銷毀時,$refs 里對應的引用不會自動清除。若不清理,可能會造成內存泄漏。所以在組件銷毀時要手動清理 $refs

<template><div><child-component ref="childRef"></child-component><button @click="destroyChild">銷毀子組件</button></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},methods: {destroyChild() {// 銷毀子組件this.$refs.childRef.$destroy();// 手動清理 $refs 里的引用this.$refs.childRef = null;}}
};
</script>

4. 避免在 watch 中頻繁訪問 $refs

watch 用于監聽數據變化,若在 watch 里頻繁訪問 $refs,會導致不必要的性能開銷。可以在 watch 中設置 immediate: false,避免初始化時就執行訪問操作。

<template><div><div ref="myElement">示例元素</div><input v-model="inputValue" /></div>
</template><script>
export default {data() {return {inputValue: ''};},watch: {inputValue: {handler(newValue) {if (this.$refs.myElement) {// 對元素進行操作this.$refs.myElement.textContent = newValue;}},immediate: false // 避免初始化時執行}}
};
</script>

5. 利用緩存機制

要是需要多次訪問 $refs,可以把訪問結果緩存起來,避免重復訪問。

<template><div><div ref="myElement">示例元素</div><button @click="doSomething">執行操作</button><button @click="doAnotherThing">執行另一個操作</button></div>
</template><script>
export default {data() {return {cachedElement: null};},methods: {getElement() {if (!this.cachedElement) {this.cachedElement = this.$refs.myElement;}return this.cachedElement;},doSomething() {const element = this.getElement();if (element) {// 對元素進行操作element.style.fontSize = '20px';}},doAnotherThing() {const element = this.getElement();if (element) {// 對元素進行另一個操作element.style.backgroundColor = 'yellow';}}}
};
</script>

通過以上這些方法,可以有效避免 $refs 訪問帶來的性能問題,提升 Vue 應用的性能和穩定性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/899349.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/899349.shtml
英文地址,請注明出處:http://en.pswp.cn/news/899349.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【安全運營】關于攻擊面管理相關概念的梳理(二)

CYNC&#xff08;持續可見性和網絡控制&#xff09; CYNC&#xff08;Continuous Visibility and Network Control&#xff09;即“持續可見性和網絡控制”&#xff0c;是一個與網絡安全和IT運營管理相關的概念。它強調的是在一個組織的數字環境中&#xff0c;確保對所有資產、…

【區塊鏈安全 | 第二篇】區塊鏈概念詳解

文章目錄 概述1. 區塊鏈類型2 區塊鏈五層架構3 賬本模型4. 節點&#xff08;Node&#xff09;5. 區塊&#xff08;Block&#xff09;6. 區塊鏈&#xff08;Blockchain&#xff09;7. 區塊鏈工作流程 核心技術1. 共識機制2. 智能合約 主要組件1. 交易&#xff08;Transaction&am…

Redisson - 分布式鎖和同步器

文章目錄 鎖&#xff08;Lock&#xff09;公平鎖&#xff08;Fair Lock&#xff09;聯鎖&#xff08;MultiLock&#xff09;紅鎖&#xff08;RedLock&#xff09; 【已廢棄】讀寫鎖&#xff08;ReadWriteLock&#xff09;信號量&#xff08;Semaphore&#xff09;可過期許可信號…

HarmonyOS:GridObjectSortComponent(兩個Grid之間網格元素交換)

一、概述 網格對象的編輯排序是用于網格對象的編輯、拖動排序、新增和刪除。 說明 該組件從API Version 11開始支持。后續版本如有新增內容&#xff0c;則采用上角標單獨標記該內容的起始版本。 二、導入模塊 import { GridObjectSortComponent, GridObjectSortComponentItem…

RFID技術在機器人中的核心應用場景及技術實現

一、機器人定位與導航 1. 地標定位系統 實現方式: 在環境關鍵點部署無源RFID標簽(如UHF Tag),機器人攜帶讀寫器通過讀取標簽ID實現絕對定位# 偽代碼:RFID地標定位 def get_robot_position():detected_tags = reader.read_tags()known_positions = {tag1: (x1,y1), tag2: …

uv 命令用conda命令解釋

uv&#xff1a;安裝 | uv-zh-cn 功能 | uv-zh-cn #showkey -a 可看按鍵的"\eOP"轉義序列是啥# 綁定快捷鍵 f1 到 source .venv/bin/activate函數 bind "\eOP": "source .venv/bin/activate " #conda activate# 綁定快捷鍵 f2 到uv add函數 …

《探秘SQL的BETWEEN:解鎖數據范圍查詢的深度奧秘》

在數據的廣袤宇宙中&#xff0c;結構化查詢語言&#xff08;SQL&#xff09;宛如一座精密的導航系統&#xff0c;引導我們穿越數據的浩瀚星河&#xff0c;精準定位所需信息。其中&#xff0c;BETWEEN作為SQL的關鍵工具之一&#xff0c;以其獨特的能力&#xff0c;在數據的海洋里…

大型語言模型的秘密:思考鏈長度與提示格式的魔力

嘿&#xff0c;朋友們&#xff01;今天我要和大家聊聊一個超級酷的話題——大型語言模型&#xff08;LLMs&#xff09; 它們在“思考”和回答問題時的一些“小秘密”。你可能已經聽說過**“思考鏈”&#xff08;Chain of Thought, COT** 這個概念&#xff0c;它是一種讓模型在回…

RHCE工程師特訓指南

RHCE&#xff08;紅帽認證工程師&#xff09;是Linux領域極具含金量的認證之一&#xff0c;其考試以實操為主&#xff0c;注重系統管理、網絡服務配置及自動化運維能力。以下內容可幫助對RHCE考生高效規劃學習路徑。 一、RHCE認證概述 認證結構 RHCE認證分為兩部分&#xff…

Vue 3 中 slot插槽的使用方法

插槽&#xff0c;名字挺新奇。但不要被他的名字難住。其實就是父組件向子件件傳遞信息的一種手段。我們可以用這樣的方法向子組件傳值。 父組件&#xff08;app.vue) <template><MyCompoent :transData"{a:reactiveObj.a,breactiveObj.b,c}"> </tem…

大模型中的召回次數是什么意思

大模型中的召回次數是什么意思 在大語言模型&#xff08;LLM&#xff09;和檢索增強生成&#xff08;RAG&#xff09;系統中&#xff0c;召回次數&#xff08;Recall Count&#xff09;是一個重要的參數&#xff0c;它決定了在檢索階段從知識庫中提取多少候選文檔或片段。這個…

智能監控視頻聚合平臺,GB28181/RTSP/SIP/RTMP直播會議融合方案

全場景智能監控聚合平臺&#xff1a;打破邊界&#xff0c;賦能高效協同 在數字化轉型加速的今天&#xff0c;海量視頻監控設備、多樣化的編碼協議與復雜的業務場景&#xff0c;讓企業面臨跨系統整合難、資源調度效率低、協作響應慢等痛點。我們的智能監控聚合平臺以技術創新為…

IP數據報報文格式

一 概述 IP數據報由兩部分組成&#xff1a;首部數據部分。首部的前一部分是固定長度&#xff0c;一共20字節大小&#xff0c;是所有IP數據報文必須具有的&#xff1b;固定部分后面是一些可選字段&#xff0c;其長度是可變的。 二 首部固定部分各字段意義 &#xff08;1&…

【電子通識】案例:為什么電子產品制造過程中使用馬克筆在FFC/FPC連接器打點進行標記

在電子產品制造過程中&#xff0c;使用馬克筆在FFC/FPC連接完成后進行打點標記&#xff08;或類似目視化檢查方法&#xff09;&#xff0c;是一種常見的“過程防錯&#xff08;Poka-Yoke&#xff09;”手段&#xff0c;其核心目的是通過簡單、直觀的方式確保關鍵工序的執行質量…

Electron應用生命周期全解析:從啟動到退出的精準掌控

一、Electron生命周期的核心特征 1.1 雙進程架構的生命周期差異 Electron應用的生命周期管理具有明顯的雙進程特征&#xff1a; 主進程生命周期&#xff1a;貫穿應用啟動到退出的完整周期渲染進程生命周期&#xff1a;與瀏覽器標簽頁相似但具備擴展能力進程間聯動周期&#…

Oracle到MySQL實時數據互通:透明網關跨庫查詢終極方案

技術架構概述 節點類型IP示例Oracle數據庫172.18.0.11透明網關節點192.168.5.20MySQL數據庫10.10.8.100 提示&#xff1a;透明網關支持部署在Oracle服務器實現集中式管理 一、MySQL環境準備 1. ODBC驅動部署 從MySQL官網獲取對應版本的ODBC驅動&#xff1a; # 企業版推薦使…

Linux中斷處理流程

Linux中斷處理流程 在Linux內核中&#xff0c;中斷控制器管理硬件中斷號到Linux中斷號的映射&#xff0c;并通過中斷描述符&#xff08;struct irq_desc&#xff09;進行管理。存儲這種映射關系的方式取決于中斷編號的連續性&#xff0c;具體實現如下&#xff1a; 1. 數組存儲&…

JVM 如何打破雙親委派模型?

雖然雙親委派模型是 Java 類加載機制的推薦實現方式&#xff0c;但在某些情況下&#xff0c;為了實現特定的功能&#xff0c;可能需要打破雙親委派模型。以下是一些常見的打破雙親委派模型的方法和場景&#xff1a; 1. 重寫 loadClass 方法 (不推薦): 原理&#xff1a; java.l…

Java 大視界 -- 基于 Java 的大數據隱私計算在醫療影像數據共享中的實踐探索(158)

&#x1f496;親愛的朋友們&#xff0c;熱烈歡迎來到 青云交的博客&#xff01;能與諸位在此相逢&#xff0c;我倍感榮幸。在這飛速更迭的時代&#xff0c;我們都渴望一方心靈凈土&#xff0c;而 我的博客 正是這樣溫暖的所在。這里為你呈上趣味與實用兼具的知識&#xff0c;也…