vue自定义指令(详解)

有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

导读:本篇文章讲解 vue自定义指令(详解),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

vue自定义指令,核心就是需要自己亲手去操作DOM

而vue中的内置指令例如v-model只不过是vue帮你动了dom上的display属性,

所以自定义指令,就是自己亲手对原生操作dom进行了一次封装

局部指令 

需求一:定义一个v-big指令,让它和v-text功能类似,把绑定的值放大10倍

我们现在自定义一个big指令,展示放大10倍的num值,让v-big指令和v-text指令作用一样

<template>
  <div class="myDiv">
        <h2>当前的n值是
              <span v-text='num'></span>
        </h2>
        <h2>放大10倍的值是
              <span v-big='num'></span>
        </h2>
        <button @click="num++">点我加1</button>
  </div>
</template>

<script>
export default {
  name: '',
  components:{},
  props:{},
  data(){
    return {
          num:10
    }
  },
  methods:{},
}
</script>
<style lang="less" scoped>

</style>

 运行之后打开控制台,发现报错了,报错的指令是big,diective就是指令的意思

vue自定义指令(详解)

下面我们就来定义这个big指令:

定义指令呢,有一个属性diectives,所有自定义指令都在里面定义

big指令定义有2种方式

(1)函数式

(2)对象式

函数式定义指令 

先讲解函数式,通过函数式,将num的值放大10倍

vue自定义指令(详解)

有人说big函数只要有个返回值就行了吧?

注意这个指令函数不是返回值,他是接收2个参数,我们先输出这2个参数

vue自定义指令(详解) 

vue自定义指令(详解)

 由此看出,a是一个dom元素。

有人说,那a是真实dom还是虚拟dom呢?

答:是真实dom。

验证:我们通过 instanceof 来判断 a 是否是html上的实例

vue自定义指令(详解)

结果是true

vue自定义指令(详解)

有人问b是啥?

答:b里面有个value,value就是v-big后面的双引号的内容,这里面是个n,因此他的value就是num的值10,还有一个expression是表达式

vue自定义指令(详解)

那如果v-big是个函数,那么value就是一个函数

 那么我们现在既可以拿到真实的dom元素,又可以通过.value拿到绑定的值,那么我们就可以写放大10倍的指令了。 将参数名换成官方定义的即可。

vue自定义指令(详解)

可以看到页面出来了

vue自定义指令(详解)

那问题来了。如果我们点击按钮让n的值加1,那么红框和蓝框的值都变吗,还是只有红框值变?

答:都变

篮框的变化取决于big函数还会不会被调用了,从验证结果来看,是会调用的

vue自定义指令(详解)

 那么big指令函数何时会被调用呢?

(1)指令与元素成功绑定时(一上来)

(2)指令所在的模板被重新解析时(并不是指令所用到的数据发生更新就被调用)

需求二:定义一个v-sbind指令,和v-bind功能类似,可以让其绑定的input元素默认获取焦点

首先我们给页面添加一个input框,里面设置绑定value值为num,v-bind简介形式为冒号:

vue自定义指令(详解)

 效果:

vue自定义指令(详解)

 我们想要用v-sbind实现相同的效果,首先先定义v-sbind指令

 vue自定义指令(详解)

注意:

focus():得到焦点时使用,blur():失去焦点时使用 

 vue自定义指令(详解)

 按理来说这就写完了,可是效果并没有实现。看下图并没有获取焦点

 vue自定义指令(详解)

 这是什么原因呢?

其实是focus执行时机的问题,上面说了指令与元素成功绑定时就会调用指令函数,成功绑定只是在内存中建立了这种绑定关系,并没有放入页面,而一上来input框就已经调用了指令函数,因此对input进行焦点的获取是不起作用的。

所以对于这种情况,我们必须精确到元素放入页面的时间点,而指令的函数式写法是不符合该需求的,这样就用到了指令的对象式写法

【对象式写法】

 里面包含三种固定的函数,分别代表不同时期的触发 

        sbind:{
            //   指令与元素成功绑定时(一上来)
              bind(){

              },
            //   指令所在元素被插入页面时
              inserted(){

              },
            //   指令所在的模板被重新解析时
              update(){

              }
        }

看下触发顺序

vue自定义指令(详解)

 这三个事件同样有element和binding两个参数

因此完整写法就是:

        sbind: {
            //   指令与元素成功绑定时(一上来)
            bind(element, bidding) {
                  // 虽然没放入页面但是不影响赋值
                  element.value = bidding.value
            },
            //   指令所在元素被插入页面时
            inserted(element, bidding) {
                  // 此时我们就可以在元素插入页面时再调用获取焦点事件
                  element.focus()
            },
            //   指令所在的模板被重新解析时
            update(element, bidding) {
                  // 页面重新解析时,同样需要再次赋值,这样可以保证num的值随之变化
                  element.value = bidding.value
            }
        }

从上面代码可以看出,bind事件和update其实是一样的,而指令的函数式就是包含的这两个方法,只不过没有inserted方法,因此遇到特殊情况就用对象式,其他情况函数式就可以满足需求~

全局指令+总结

(1)命名方式

多个单词命名用 – 分隔,例如:v-big-number

定义指令的时候用单引号包裹:’v-big-number'(){ }

(2)指令回调函数中的this指向

所有指令相关的this,不是vm是window

(3)以上我们所讲解的指令都是局部指令,只能在本vue实例中使用

假如我们相把v-sbind变为全局指令:

直接在main.js中,通过vue调用directive,将sbind对象复制进来就是全局的了,所有页面都可以使用。

Vue.directive('sbind', {
  //   指令与元素成功绑定时(一上来)
  bind(element, bidding) {
    // 虽然没放入页面但是不影响赋值
    element.value = bidding.value
  },
  //   指令所在元素被插入页面时
  inserted(element, bidding) {
    // 此时我们就可以在元素插入页面时再调用获取焦点事件
    element.focus()
  },
  //   指令所在的模板被重新解析时
  update(element, bidding) {
    // 页面重新解析时,同样需要再次赋值,这样可以保证num的值随之变化
    element.value = bidding.value
  }
})

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/149689.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!