DAY22 | 跟 Vue.js 認識的30天 - Vue 常用 API 說明(`$refs`)

使用 Vue 之後,我們就很少去操作 DOM 了,但如果真的需要去操作 DOM 時怎麼辦?還是跟之前寫 JavaScript 一樣嗎?一定寫一長串的 document.querySelector('.className') 嗎?不! Vue 提供了一個可以快速取得 DOM 元素的屬性 — $refs 。接下來就來了解一下$refs 屬性。

利用 $refs 取得 DOM 元素

在使用 Vue 屬性 $refs 前取得 DOM 元素前,必須先透過 HTML Attribute ─ ref 來將該 DOM 元素的資料註冊到實例的 $refs 裡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 將 p 這個 DOM 元素以 text 名註冊到 $refs 裡-->
<p ref="text">hello</p>

<script>
const vm = new Vue({
el: "#vm",
created() {
// 取得 $refs
console.log(this.$refs);
// 以 this.$refs.text 來取得 DOM 元素 - p 標籤 → 失敗
// $refs 是在 created 前即完成初始化,所以可以取得 this.$refs的值(但 DOM 元素還不存在),但是必須注意到真正的 DOM 元素會是在 mounted 時才真正被掛載到實例上
console.log(this.$refs.text); //undefined
},
mounted() {
// 取得 $refs
console.log(this.$refs);
// 以 this.$refs.text 來取得 DOM 元素 - p 標籤 → 成功
console.log(this.$refs.text);
}
});
</script>

關於 $refs 的出現時機及使用時機,可以參考DAY02 | 跟 Vue.js 認識的30天 - Vue 實體的生命週期(Lifecycle Hooks)及模板語法(Template Syntax) 或是下圖。

利用 $refs 取得子模組

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<child-component ref="greet"></child-component>
<script>
Vue.component("child-component", {
template: `<div>
<p class="text" ref="hello" @click="log">hello</p>
</div>`,
methods: {
log(){
//子模組
console.log('component','this',this);
// 取得實例裡(該模組)的 $refs
console.log('component',this.$refs);
// 以 this.$refs.hello 來取得實例裡(該模組)的 DOM 元素 - P 標籤
console.log('component',this.$refs.hello);
}
}
});
const vm = new Vue({
el: "#vm",
mounted() {
// vm
console.log('mounted','this',this);
// 取得實例裡的 $refs
console.log('mounted',this.$refs);
// 以 this.$refs.greet 來取得子模組
console.log('mounted',this.$refs.greet);
}
});
</script>

透過 $refs 取得子模組 ↓↓↓

在子模組中透過 $refs 取得 DOM 元素 ↓↓↓

注意事項

透過練習發現 $refs 屬性的確在 created() 階段就存在,但如果要取得該屬性裡的 DOM 元素或是子模組都會失敗,這是因為 $refs 屬性在 Vue init 階段即會被初始化,所以可以透過 this.$refs 取得 ref 資料,但是如果要再進一步取得 DOM 元素或是子模組就會失敗了(DOM 元素或是子模組還不存在),這是因為真正的 DOM 元素或是子模組還沒被渲染出來,他們是在 mounted() 階段才真正存在。

Vue 文件也特別提醒: $refs 不是響應式的,所以不要試圖使用資料綁定;要避免在模板或計算屬性中訪問 $refs

Demo

See the Pen DAY22 | 跟 Vue.js 認識的30天 - Vue 常用 API 說明(`$refs`) by Celeste6666 (@celeste6666) on CodePen.

參考資料:

Vue.js - API - ref

Vue.js - API - $refs

Vue.js - 访问子组件实例或子元素