前言
通常情況下,vue
內置的指令並不能夠滿足我們日常開發的要求,我們則可以根據實際需要進行自定義指令,本篇博客將記錄vue自定義指令模擬v-model
的過程,有什麼錯誤的地方歡迎批評指正。
創建自定義指令
// 全局創建
Vue.directive("slice",{
bind(el,bindings,vnode){
// 指令綁定上去的時候觸發
},
update(el,bindings,vnode){
// 數據更新的時候觸發
},
inserted(el){
// 元素插入到頁面的時候觸發
}
})
// 局部創建
new Vue({
el: "#app",
directives: {
slice: {
bind(el, bindings, vnode) {
// 指令綁定上去的時候觸發
},
update(el, bindings, vnode) {
// 數據更新的時候觸發
},
inserted(el) {
// 元素插入到頁面的時候觸發
}
}
}
})
創建自定義指令分爲全局創建和局部創建,自定義指令有三個鉤子函數( bind、update和inserted )
鉤子函數
bind、update和inserted
鉤子函數 | 參數 | 描述 |
---|---|---|
bind | el,bindingd,vnode | 綁定指令時觸發 |
update | el,bindingd,vnode | 數據更新數觸發 |
inserted | el | 插入到頁面時觸發 |
其中el
代表着當前元素,bindings
爲一個對象,vnode
是虛擬DOM
。
比如說當我想要在頁面加載完成後input
框獲取焦點,我們可以這樣寫
<div id="app">
<input type="text" v-slice>
</div>
<script>
Vue.directive("slice", {
bind(el, bindings, vnode) {},
update(el, bindings, vnode) {},
inserted(el, bindings, vnode) {
el.focus();
}
})
new Vue({
el: "#app"
})
</script>
參數 bindings
指令可以傳遞變量,我們可以通過bindings
對象中的expression
獲取參數值的變量名。
<div id="app">
<input type="text" v-slice="content">
</div>
<script>
Vue.directive("slice", {
bind(el, bindings, vnode) {
console.log(bindings.expression)
},
update(el, bindings, vnode) {},
inserted(el, bindings, vnode) {
el.focus();
}
})
new Vue({
el: "#app",
data: {
content: 'hello vue'
}
})
</script>
參數 vnode
有了自定義的參數值的變量名,我們就可以在vnode
中獲取到變量的數據
<div id="app">
<input type="text" v-slice="content">
</div>
<script>
Vue.directive("slice", {
bind(el, bindings, vnode) {
var context = vnode.context;
console.log(vnode.context);
console.log(vnode.context[bindings.expression]);
},
update(el, bindings, vnode) {},
inserted(el, bindings, vnode) {
el.focus();
}
})
new Vue({
el: "#app",
data: {
content: 'hello vue'
}
})
</script>
參數 el
有了變量的數據,我們可以將數據設置爲input
框的value
值。
<div id="app">
<input type="text" v-slice="content"> {{content}}
</div>
<script>
Vue.directive("slice", {
bind(el, bindings, vnode) {
var context = vnode.context;
el.value = context[bindings.expression];
},
update(el, bindings, vnode) {},
inserted(el, bindings, vnode) {
el.focus();
}
})
new Vue({
el: "#app",
data: {
content: 'hello vue'
}
})
</script>
數據雙向綁定
我們爲元素綁定輸入事件,每次輸入時將數據更新到data
中。
<div id="app">
<input type="text" v-slice="content"> {{content}}
</div>
<script>
Vue.directive("slice", {
bind(el, bindings, vnode) {
var context = vnode.context;
el.value = context[bindings.expression];
el.oninput = e => {
var value = e.target.value;
context[bindings.expression] = value;
}
},
update(el, bindings, vnode) {},
inserted(el, bindings, vnode) {
el.focus();
}
})
new Vue({
el: "#app",
data: {
content: 'hello vue'
}
})
</script>
指令參數屬性
指令可以添加參數和一些指令,這些都被保存在bindings
中。
<div id="app">
<input type="text" v-slice:11.number="content"> {{content}}
</div>
限制數據的長度
<div id="app">
<input type="text" v-slice:11.number="content"> {{content}}
</div>
<script>
Vue.directive("slice", {
bind(el, bindings, vnode) {
var context = vnode.context;
el.value = context[bindings.expression];
// 數據雙向綁定
el.oninput = e => {
var value = e.target.value;
context[bindings.expression] = value;
}
// 限制長度
var length = bindings.arg;
if (length) {
var initval = context[bindings.expression].slice(0, length);
context[bindings.expression] = initval;
el.value = initval;
}
},
update(el, bindings, vnode) {
var context = vnode.context;
// 限制長度
var length = bindings.arg;
if (length) {
var initval = context[bindings.expression].slice(0, length);
context[bindings.expression] = initval;
el.value = initval;
}
},
inserted(el, bindings, vnode) {
el.focus();
}
})
new Vue({
el: "#app",
data: {
content: 'hello vue123213213123213213safsadqwewqeqweqwe'
}
})
</script>
限制數據內容
<div id="app">
<input type="text" v-slice:11.number="content"> {{content}}
</div>
<script>
Vue.directive("slice", {
bind(el, bindings, vnode) {
var context = vnode.context;
el.value = context[bindings.expression];
// 數據雙向綁定
el.oninput = e => {
var value = e.target.value;
context[bindings.expression] = value;
}
// 限制長度
var length = bindings.arg;
if (length) {
var initval = context[bindings.expression].slice(0, length);
context[bindings.expression] = initval;
el.value = initval;
}
// 設置爲number
var IsNumber = bindings.modifiers.number;
if (IsNumber) {
var initval = context[bindings.expression].replace(/[^0-9]/g, '');
context[bindings.expression] = initval;
el.value = initval;
}
},
update(el, bindings, vnode) {
var context = vnode.context;
// 限制長度
var length = bindings.arg;
if (length) {
var initval = context[bindings.expression].slice(0, length);
context[bindings.expression] = initval;
el.value = initval;
}
// 設置爲number
var IsNumber = bindings.modifiers.number;
if (IsNumber) {
var initval = context[bindings.expression].replace(/[^0-9]/g, '');
context[bindings.expression] = initval;
el.value = initval;
}
},
inserted(el, bindings, vnode) {
el.focus();
}
})
new Vue({
el: "#app",
data: {
content: 'hello vue123213213123213213safsadqwewqeqweqwe'
}
})
</script>
總結
就這樣,一個自定義的指令完成了,我們從以上的自定義中簡化的模擬了v-model
的指令,當然也可以你自定義其他的指令,快去試一下吧~