第三十九篇 自定义指令 - directive

         前面讲了关于在Vue中如何来进行封装swiper组件的内容,本篇内容讲到使自定义组件,讲这块内容也是同样为了后续再次回顾封装swiper组件变化做铺垫内容,那么什么是自定义指令,在前面的内容讲过了好些常用的指令,如 v-modle、v-bind、v-show、v-if、v-for、v-else等等相关的指令来说就已经基本够用,而为什么出现自定义指令只再一些情况之下需要对DOM元素进行底层操作,那么就能够将其封装在指令当中,这样一来在使用的话就看不到对DOM元素进行底层操作,说到底自定义指令的目的就是为了对DOM元素进行底层操作;将底层操作封装到指令当中,其实是能够达到复用效果。下面来进行一个对自定义指令的学习使用:

全局自定义指令 - directive使用

 通过一个简单的例子来演示:

<div id="app">
    <div v-msg>
        温馨提示
    </div>
</div>
<script>
    // 自定义指令 "v-msg"
    Vue.directive("msg",{
        // 指令生命周期之一 inserted
        inserted(el){
            console.log("绑定当前指令的标签插入父节点就会执行",el)
        }
    })
    new Vue({
        el:'#app',
        
    })
</script>

        编写自定义指令"v-msg",inserted是指令的生命周期之一,前面讲到的是组件的八个生命周期,inserted是什么呢?就是 v-msg 绑定的标签插入到DOM节点上就会执行 inserted 指令生命周期,那么上面讲到使用自定义指令其实就是就是要操作底层的DOM,那么打印 inserted(el) 中的第一个参数,可以通过效果看到可以访问到原生的DOM,自定义指令的本意其实也是为了让你能够访问原生DOM,解决在某些特性情况下你需要对底层DOM的操作;

        下面来进行inserted时对绑定的内容做改变:当绑有 v-msg 指令插入父节点的时候它会出现一个边框的效果(1px solid black);

<script>
    // 自定义指令 "v-msg"
    Vue.directive("msg",{
        // 指令生命周期之一 inserted
        inserted(el){
            console.log("绑定当前指令的标签插入父节点就会执行",el)
            el.style.border = "1px solid black"
        }
    })
    new Vue({
        el:'#app',
        
    })
</script>

        那么在之前使用的 v-if 、v-show 等的一些指令能够通过传一个属性来控制,那么自定义指令 v-msg 想通过传值来更改效果行不行呢?测试一下:

<div id="app">
    <div v-msg="red">温馨提示</div>
</div>

 控制台会出现报错:

[Vue warn]: Property or method "red" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. 

        "red"未在实例上定义,通过初始化属性,确保此属性在 data 选项中或对于基于类的组件是反应性的。 

         那么在此需要知道一个问题,使用v-if,v-show的这些传值是当成一个变量来进行使用的,那么在此的 red 是通过字符串的形式,那么就该使用一个引号;使用 inserted 的第二个参数 binding ,也即是绑定的内容,下面来看一下:

<div id="app">
    <div v-msg=" 'red' ">温馨提示</div>
</div>
Vue.directive("msg",{
    // 指令生命周期之一 inserted
    inserted(el,binding){
        console.log(binding);
        console.log("binding.value:",binding.value);
...

         通过打印 binding 可以看到关于组件的内容,通过binding。binding.value 能够获取到绑定的值字符串 red,这样就可以来进行操作;

<div id="app">
    <div v-msg="'red'">
        温馨提示
    </div>
</div>
<script>
Vue.directive("msg",{
    // 指令生命周期之一 inserted
    inserted(el,binding){
            el.style.border = "1px solid " + binding.value
        }
    })
    new Vue({el:'#app'})
</script>

        v-msg 传过去一个字符串red值,那么对应绑定v-msg的标签会有一个像素的实线红色边框;来看测试效果:

        那么如果想附上一个蓝色或是绿色的边框,可以通过v-msg自定义指令然后以字符串的形式传入颜色:

<div v-msg="'blue'">温馨提示</div>
<div v-msg="'green'">温馨提示</div>

        此时你又不想在 v-msg 当中把值写固定了,可以通过一个data定义一个变量:

<div id="app">
    <div v-msg="mycolor">
        温馨提示
    </div>
</div>
<script>
Vue.directive("msg",{
    // 指令生命周期之一 inserted
    inserted(el,binding){
            el.style.border = "1px solid " + binding.value
        }
    })
    var vm = new Vue({
        el:'#app',
        data:{
            mycolor:"red"
        }
    })
</script>

        这样编写可以显示出来,但有什么问题呢?我通过控制台输入这样一个命令来更改 mycolor 是否会得到更新呢?

        怎么还是红色呢?不应该是蓝色吗?inserted 是我们插入父节点的时候进行触发的,而对数据的更新并没有,此时data数据是最新的,但DOM节点的数据仍然是旧数据,那么就需要在指令中的update周期进行数据更新;下面看编写代码和测试效果:

Vue.directive("msg",{
    // 指令生命周期之一 inserted
    inserted(el,binding){
        el.style.border = "1px solid " + binding.value
    },
    update(el,binding){
        el.style.border = "1px solid " + binding.value
    }
    })

        以上就是自定义的一个指令,虽然实际不会做这样一个比较无趣的指令,但通过这个例子能够对自定义指令有着一定的认识和了解;


        下面进一步的观察代码会发现一个问题,指令的生命周期 inserted 和update 中的内容一样,inserted 是内容插入父节点是发生,而update是数据更新发生,刚好这个自定义指令也确实需要这么写,但是既然这两个内容都是一样的,那么可以换一种方式,将它编写成一个函数,在创建和更新的时候都会被调用执行的;下面来看一下这种方式是怎样:

Vue.directive("msg",function(el,binding){
    el.style.border = "1px solid " + binding.value
})

测试效果:


局部自定义指令 - directives使用

        上面是在全局当中来使用自定义指令,那么如果在封装组件的时候,仅为了组件的使用需要用局部的自定义指令,那么在组件中如何让来用局部的自定义指令呢? —— directives

1. 编写代码

Vue.component("child",{
    template:`
        <div>
            <input type="text" v-focus />
            <button>搜索</button>
        </div>
    `,
    directives:{
        // 指令名称
        focus:{
            inserted:function(el){
                el.focus()
            }
        }
    }
})

        通过设置 directives 来进行注册局部指令,这个指令名称是focus,当input标签绑定 v-focus 时在组件插入到父节点当中时会自动获取焦点;

2. 测试效果

        那么通过以上自定义指令的一个认识学习,为什么说自定义指令其实就是操作底层DOM ,还记得前面讲的swiper吗?为什么在Vue中会有初始化过早之类的一些问题,在其他像jquery使用就不需要担心这些问题,在Vue当中非常依赖DOM,需要去注意它会在什么时候创建完成,先前从mounted生命周期尝试再转到updated生命周期在回到mounted生命周期,通过设置key或者v-if指令一点一点去尝试才知道,那么指令的目的也就并非是一定要去操作DOM,而是它知道什么时候DOM刚刚创建完成,知道这个,我们再一次踏上了封装swiper组件的一个路程。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵魂学者

你的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值