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">
    

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">
    <!--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>