Vue
不僅提供了豐富的內置指令用於操作DOM
元素,還允許開發者創建自定義指令。透過自定義指令,我們可以對DOM
元素進行更細緻的控制,並在指令的不同生命週期階段執行特定的邏輯,從而實現更靈活的功能擴展。
【 指令常用的生命週期 】
⭐ 自定義指令應主要用於直接操作DOM
的場景。對於其他需求,優先考慮使用內置指令(如v-bind
)進行聲明式的模板處理,這樣能提升代碼的可讀性與效率。
這裡透過實作自定義指令v-focus
,說明使用自定義指令來控制DOM
元素相比於其他方式(如原生autofocus
屬性和ref
)的優勢。自定義指令可以更靈活地控制元素的焦點行為,並且在元素插入或更新時都能確保獲取焦點。
【 v-focus 自定義指令實做方式 】
👉 Vue3 Options API 自定義指令區域註冊實作連結
Vue Template:
<div id="app">
<button @click="changeButtonVisible" type="button">toggle</button>
<div v-if="isVisible" class="input-group">
<label for="text-input">我是輸入框:</label>
<input v-focus id="text-input" type="text">
</div>
</div>
javascript:
const focus = {
mounted: (el) => el.focus()
};
const rootComponent = {
data() {
return {
isVisible: false
};
},
methods: {
changeButtonVisible() {
this.isVisible = !this.isVisible;
}
},
directives: { focus }
};
【 ref 實做修改方式 】
👉 Vue3 Options API ref mounted focus實作連結
Vue Template:
<input v-if="isVisible" id="text-input" ref="inputVal" type="text">
javascript:
mounted(){
this.$refs.inputVal.focus()
}
【 原生 HTML autofocus 屬性 】
Vue Template:
<input v-if="isVisible" id="text-input" type="text" autofocus>
無論是使用ref
來手動設置焦點,還是使用原生 HTML autofocus
屬性,這些方法都相對較難精確地處理元素在創建和銷毀時的焦點控制問題,通常只能在初始化時賦予輸入框焦點,但在點擊toggle
後,無法保持持續的焦點效果。而自定義指令可以更自然地與元素的生命週期鉤子結合,從而在元素插入或移除時進行更靈活的操作。
自定義指令可以透過區域註冊或全域註冊來使用,根據不同的應用場景,我們可以選擇合適的註冊方式:
以上面v-focus
自定義指令案例說明不同的註冊方式:
👉 Vue3 Options API ref mounted focus實作連結
javascript - 區域註冊指令(v-focus)
const focus = {
mounted: (el) => el.focus()
};
const rootComponent = {
directives: { focus }
};
javascript - 全域註冊指令(v-select)
const app = createApp(rootComponent);
app.directive("select", {
mounted: (el) => el.select()
});
在自定義指令中,使用不同的Hook
時可以訪問一些常見的參數:
beforeUpdate
和updated
hook 中可用。無論值是否更改,oldValue 都可用。⭐ 除了el
參數之外其餘參數都是唯獨屬性。如果要跨不同 Hook 傳值使用,官方推薦使用dataset attribute
的方式。
以下是一個範例說明如何使用自定義指令來暫存表單數據至localStorage
,並結合前述的參數使用方式:
👉 Vue3 Options API 表單自定義指令 v-localStorage 實作連結
流程說明:
localStorage
進行緩存localStorage
顯示未送出前的內容Vue Template:
<form v-localstorage:UserInfo @submit.prevent>
<div class="input-group">
<label for="username">用戶名:</label>
<input type="text" id="username" name="username" />
</div>
<div class="input-group">
<label for="phone">電話號碼:</label>
<input type="tel" id="phone" name="phone" />
</div>
<button type="submit">提交</button>
</form>
javascript(簡化版本):
const localStorage = {
mounted(el, binding) {
// 取得 arg 的參數
const key = binding.arg || "formData";
const savedData = JSON.parse(window.localStorage.getItem(key)) || {};
populateForm(el, savedData);
function handler() {
const formData = getFormData(el);
window.localStorage.setItem(key, JSON.stringify(formData));
// 同步更新 Vue 中的響應式數據
if (binding.instance && binding.instance.storageData) {
binding.instance.storageData = formData;
}
}
el.addEventListener("change", handler);
// 將 handler 保存到元素上,以便後續移除
el._localStorage_handler = handler;
},
unmounted(el) {
// 如果存在處理函數,則移除事件監聽器
if (el._localStorage_handler) {
el.removeEventListener("change", el._localStorage_handler);
delete el._localStorage_handler;
}
}
};
自定義指令為Vue
開發提供了一種靈活的方式來封裝對DOM
元素的操作,允許在元素的不同生命週期鉤子中進行控制,以實現特定功能需求。然而需要注意的是,自定義指令無法像屬性透傳那樣被深層組件使用,因此不建議直接應用於組件,避免多個根節點帶來的潛在問題。
這次提供一個結合Bootstrap
樣式的輸入框,並通過 Vue.js 自定義指令v-validate
來實現即時的驗證。指令會在updated
生命週期中取得用戶的輸入值進行驗證,根據結果應用對應的Bootstrap
樣式,顯示輸入的有效或無效狀態。
Vue3 Options API 自定義指令 v-validate - 電子信箱驗證(模板)
Vue3 Options API 自定義指令 v-validate - 電子信箱驗證(完成版)