此筆記僅以個人理解方式記錄
平常我們在 html 上常看到的例如 v-for、v-model 等等... 也是VUE已經幫我們定義好的指令,而這次我們可以依這自己的需求來建立。
此功能屬於較進階的功能,因此實戰中會比較少見,市面上還是有不少完善的套件能達到同樣效果,建議可以先往這方面察找。
通常都會以 v-{ 自定義名稱 } 來命名,例如 v-validator 。
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script type="module">
const app = Vue.createApp({
data() {
return {
text: '',
}
},
});
app.mount('#app');
</script>
// v-validator
app.directive('validator', {
// directive 生命週期
mounted(el, binding) {
// 生成的同時觸發
},
updated: function (el, binding, vnode) {},
})
這邊先以 input 標籤為範例並加上 v-validator
<input type="email" v-model="text" v-validator>
再來將 focus() 加入自定義屬性 mounted 內
app.directive('validator', {
mounted(el, binding) {
el.focus();
},
updated: function (el, binding, vnode) {},
})
重新整理後可以發現 input 處於被選取的狀態,這樣就清楚知道 el 表示為有使用自定義屬性的 DOM ,我們也可以套過指令的方式將 class 加到 DOM 上面。
這邊以 form-control 為例 :
這邊要以”字串”
加入
<input type="email" v-model="text" v-validator="'form-control'">
並在 mounted 補上 console.log(binding)
app.directive('validator', {
mounted(el, binding) {
el.focus();
console.log(binding)
},
updated: function (el, binding, vnode) {},
})
這時 consloe 就可以看到我們傳入的內容
我們可以利用此方式來對其加入該 CSS
app.directive('validator', {
mounted(el, binding) {
el.focus();
el.className = binding.value
},
updated: function (el, binding, vnode) {},
})
而當 input 有變動時,將會調用 updated
app.directive('validator', {
mounted(el, binding) {
...
},
updated: function (el, binding, vnode) {
console.log('update', el, binding, vnode);
},
})
會出現以下 3 個資訊
而 binding -> instance -> text 更可以看到 input 上的東西
進一步做驗證功能,先取出 className 名稱,在取當前 v-model 的 key
app.directive('validator', {
mounted(el, binding) {
...
},
updated: function (el, binding, vnode) {
// 取出 className 名稱
const className = binding.value;
// 尋找當前的 model 名稱(取得 key 值,並帶入第一個)
const currentModel = Object.keys(binding.instance)[0];
// 從當前 Model 取值
const value = binding.instance[currentModel];
},
})
開始驗證是否為 email
app.directive('validator', {
mounted(el, binding) {
...
},
updated: function (el, binding, vnode) {
// 取出 className 名稱
const className = binding.value;
// 尋找當前的 model 名稱(取得 key 值,並帶入第一個)
const currentModel = Object.keys(binding.instance)[0];
// 從當前 Model 取值
const value = binding.instance[currentModel];
const re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
if (!re.test(value)) {
el.className = `${className} is-invalid`
} else {
el.className = `${className} is-valid`
}
},
})
由此就可以做出類似驗證的功能