返回
Featured image of post Vue自定义指令

Vue自定义指令

Vue自定义指令

指令

指令 (Directives): 是带有 v- 前缀的特殊属性, 职责是,当表达式的值改变时, 将其产生的连带影响,响应式地作用于 DOM。

内置指令

先来看看Vue中的内置指令

  • v-bind: 响应并更新DOM特性;例如:v-bind:href v-bind:class v-bind:title v-bind:bb

  • v-on:用于监听DOM事件; 例如:v-on:click v-on:keyup

  • v-model:数据双向绑定;用于表单输入等;例如:

    <input v-model="message">
    
  • v-show:条件渲染指令,为DOM设置css的style属性

  • v-if:条件渲染指令,动态在DOM内添加或删除DOM元素

  • v-else:条件渲染指令,必须跟v-if成对使用

  • v-for:循环指令;例如:

    <li v-for="(item,index) in todos"></li>
    
  • v-else-if:判断多层条件,必须跟v-if成对使用

  • v-text:更新元素的textContent;例如:

    <span v-text="msg"></span>
    

    等同于

    <span>{{msg}}</span>
    
  • v-html:更新元素的innerHTML

  • v-pre:不需要表达式,跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度;例如:

    <span v-pre>{{ this will not be compiled }}</span>
    
  • v-cloak:不需要表达式,这个指令保持在元素上直到关联实例结束编译

  • v-once:不需要表达式,只渲染元素或组件一次,随后的渲染,组件/元素以及下面的子元素都当成静态页面不在渲染

自定义指令

局部自定义指令

<template>
    <div>
        <span v-multiply="number"></span>
        <br>
        <br>
        <span>number:{{number}}</span>
        <br>
        <br>
        <button @click="number++">操作</button>
    </div>
</template>

<script>
export default {
    name: 'WorkspaceJsonTestCom',

    data() {
        return {
            number: 1
        };
    },
    directives: {
        
    }
};
</script>

函数式

先来看看函数式的参数

  • element

    指令所绑定的元素,可以用来直接操作 DOM 。

  • binding

    • name:指令名,不包含v-的前缀;

    • value:指令的绑定值;例如:v-my-directive=“1+1”,value的值是2;

    • oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子函数中可用,无论值是否改变都可用;

    • expression:绑定值的字符串形式;例如:v-my-directive=“1+1”,expression的值是'1+1';

    • arg:传给指令的参数;例如:v-my-directive:foo,arg的值为 ‘foo’;

    • modifiers:一个包含修饰符的对象;例如:v-my-directive.a.b,modifiers的值为{‘a’:true,‘b’:true}

  • vnode

    Vue编译的生成虚拟节点。

  • oldVnode

    上一次的虚拟节点,仅在update和componentUpdated钩子函数中可用。

现在以函数式实现一个简单的功能,使用自定义v-multiply将number*10并展示在页面

directives: {
    multiply(element, binding, vnode, oldVnode) {
        element.innerText = '指令number:' + binding.value * 10
    }
}

效果

对象式

再来看看对象式

对象式有着自己的生命周期函数

  • 页面加载时:bind inserted
  • 更新组件:update componentUpdated
  • 卸载组件:unbind
  • 重新安装组件:bind inserted

注意区别:bind与inserted:bind时父节点为null,inserted时父节点存在;update与componentUpdated:update是数据更新前,componentUpdated是数据更新后。

还是上面的功能,以对象式完成

directives: {
    // 对象式
    multiply: {
        // 指令与元素成功绑定
        bind(element, binding) {
            element.innerText = '指令number:' + binding.value * 10
        },
        // 指令所在元素被插入页面式
        inserted(element, binding) {

        },
        // 指令所在的模板被重新解析时
        update(element, binding) {
            element.innerText = '指令number:' + binding.value * 10
        }
    }
}

效果

全局自定义指令

使用组件的directives选项注册局部自定义指令只能在该组件内使用,在别的组件使用会报错。

接下来使用Vue.directive(id,definition)注册全局自定义指令

感觉和过滤器一样😀

函数式

Vue.directive('multiply', function(element, binding) {
	element.innerText = '指令number:' + binding.value * 10
})

对象式

Vue.directive('multiply', {
        // 指令与元素成功绑定
        bind(element, binding) {
            element.innerText = '指令number:' + binding.value * 10
        },
        // 指令所在元素被插入页面式
        inserted(element, binding) {

        },
        // 指令所在的模板被重新解析时
        update(element, binding) {
            element.innerText = '指令number:' + binding.value * 10
        }
    }
)

一些小坑

命名

在定义指令名字的时候如果很长一般以变量的习惯会以驼峰命名

<span v-multiplyXxxx="number"></span>

但是以Vue内置指令如v-else-if,官方是不建议这么写的然后改一改

这时候就不能简写了,要写成下面这样

this的问题

我们输出看看指令函数中的this

这是函数式中的

这是对象式中的

可以看到在这里面的this并不是Vm实例,所以不要搞混了哦😉

Licensed under CC BY-NC-SA 4.0
Built with Hugo
Theme Stack designed by Jimmy