vue中指令分为全局指令和局部指令
先来看全局自定义指令:
第一个参数是指令的名字,第二个参数可以是函数也可以是对象,先来看函数:
<body>
<div id="app">
<input type="text" v-slice="content" v-model="content">
</div>
<script>
Vue.directive('sice', (el, bindings, vnode) => {
console.log(el); // el是指令所在的dom元素
console.log(bindings); // 存放绑定的信息
console.log(vnode); // 虚拟节点,指令绑定元素1的节点
});
const vm = new Vue({
el: '#app',
data: {
content: ''
}
})
</script>
</body>
函数中接收三个参数:
el在这里是input元素
bindings里是一些绑定信息:
其中expression是指绑定的变量名字,这里是content
name是指令名字
value是绑定数据的值,上面content为空,所以目前value为空
v-slice上还可以写修饰符
<div id="app">
<input type="text" v-slice.number="content" v-model="content">
</div>
还可以传参:
<div id="app">
<input type="text" v-slice:9.number="content" v-model="content">
</div>
vnode虚拟节点:
vnode中contex是vue实例,其中的content是vue中的content值,即通过vnode.context拿到vue实例
小demo:规定input框中只能输入5位
<body>
<div id="app">
<input type="text" v-slice:9.number="content" v-model="content">
{{ content }}
</div>
<script>
Vue.directive('sice', (el, bindings, vnode) => {
const val = bindings.value.slice(0, 5);
vnode.context.content = val;
});
const vm = new Vue({
el: '#app',
data: {
content: ''
}
})
</script>
</body>
再利用对象的形式实现:
<script>
// Vue.directive('sice', (el, bindings, vnode) => {
// const val = bindings.value.slice(0, 5);
// vnode.context.content = val;
// });
Vue.directive('sice',{
bind(el, bindings, vnode) {
// 将指令绑定给dom元素时执行,只执行一次
},
update(el, bindings, vnode) {
// 虚拟dom渲染时执行
const val = bindings.value.slice(0, 5);
vnode.context.content = val;
}
})
const vm = new Vue({
el: '#app',
data: {
content: ''
}
})
</script>
bind + update 等于之前的函数
第三个对象:(不常用)
insert(el) {
// 当元素插入到页面中执行
el.focus();// 实现聚焦效果
}
完善一下:在这个demo中用到两个指令,v-slice和v-model ,不太合适,所以要v-slice自己实现双向数据绑定:
<div id="app">
<input type="text" v-slice:9.number="content" v-model="content">
{{ content }}
</div>
<script>
Vue.directive('sice',{
bind(el, bindings, vnode) {
// 第一步,数据显示在input框中
const context = vnode.context;
// el.value = context; (content时动态的,不能写死, 下面形式)
el.value = context[bindings.expression];
// 第二步,input变化,content也要跟着变化,所以要坚挺input
el.oninput = e => {
const value = e.target.value;
const val = value.slice(0, 5);
context[bindings.expression] = val;
// content内容被约束了,input中也要被需要被约束
el.value = val;
}
},
update(el, bindings, vnode) {
}
此功能实现了,但是当data中content值被提前设置后,出现此情况
const vm = new Vue({
el: '#app',
data: {
content: 'dsfgfhghgf'
}
})
所以取value值时应先对其进行截取
Vue.directive('sice',{
bind(el, bindings, vnode) {
// 第一步,数据显示在input框中
const context = vnode.context;
// el.value = context; (content时动态的,不能写死, 下面形式)
el.value = context[bindings.expression].slice(0, 5);
又发现content值很长
Vue.directive('sice',{
bind(el, bindings, vnode) {
const context = vnode.context;
let initVal = context[bindings.expression].slice(0, 5);
el.value = initVal;
context[bindings.expression] = initVal;
截取想要是长度,可根据
v-slice:9.number这个属性
<body>
<div id="app">
<input type="text" v-slice:9.number="content">
{{ content }}
</div>
<script>
Vue.directive('sice',{
bind(el, bindings, vnode) {
const context = vnode.context;
const length = bindings.arg || 5;// arg时参数,没有则是5
let initVal = context[bindings.expression].slice(0, length);
el.value = initVal;
context[bindings.expression] = initVal;
el.oninput = e => {
const value = e.target.value;
const val = value.slice(0, length);
context[bindings.expression] = val;
el.value = val;
}
},
这里限制9位数
在控制台更改content值:
发现input中的值没变。要想同步更新,需写在update中
el.oninput = e => {
const value = e.target.value;
const val = value.slice(0, length);
context[bindings.expression] = val;
el.value = val;
}
增加功能:.number时不能有字母出现
Vue.directive('sice',{
bind(el, bindings, vnode) {
const context = vnode.context;
const length = bindings.arg || 5;
const numberFlag = bindings.modifiers.number;
let initVal = context[bindings.expression];
if (numberFlag) {
initVal = initVal.replace(/[^0-9]/g, '');
}
el.value = initVal.slice(0, length);
el.value = initVal;
context[bindings.expression] = initVal;
el.oninput = e => {
let value = e.target.value;
if (numberFlag) {
value = value.replace(/[^0-9]/g, '');
}
const val = value.slice(0, length);
context[bindings.expression] = val;
el.value = val;
}
},
update中也要做处理
update(el, bindings, vnode) {
let context = vnode.context;
const numberFlag = bindings.modifiers.number;
let value = context[bindings.expression];
if (numberFlag) {
value = value.replace(/[^0-9]/g, '')
}
el.value = value;
}
局部指令:
<div id="app">
<input type="text" v-slice:9.number="content">
{{ content }}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
content: 'dsfgfhghgf'
},
directives: {
slice: (el, bindings, vnode) => {
}
}
})
</script>