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"> | |||||||||||||||||||||||||||||||||||
| 
 | |||||||||||||||||||||||||||||||||||
| </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"> | |
| <!--swig1--> | |
| </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"> | |
| <!--swig2--> | |
| </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"> | |
| <!--swig3--> | |
| </div> | |
| <script> | |
| const vm = new Vue({ | |
| el: '#app', | |
| data: { | |
| content: 'dsfgfhghgf' | |
| }, | |
| directives: { | |
| slice: (el, bindings, vnode) => { | |
|         } | |
|       } | |
| }) | |
| </script> | 
  </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"> | |
| <!--swig1--> | |
| </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"> | |
| <!--swig2--> | |
| </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"> | |
| <!--swig3--> | |
| </div> | |
| <script> | |
| const vm = new Vue({ | |
| el: '#app', | |
| data: { | |
| content: 'dsfgfhghgf' | |
| }, | |
| directives: { | |
| slice: (el, bindings, vnode) => { | |
|         } | |
|       } | |
| }) | |
| </script> | 
