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


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

    全局自定义指令 - directive使用

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

    1. <div id="app">
    2. <div v-msg>
    3. 温馨提示
    4. div>
    5. div>
    6. <script>
    7. // 自定义指令 "v-msg"
    8. Vue.directive("msg",{
    9. // 指令生命周期之一 inserted
    10. inserted(el){
    11. console.log("绑定当前指令的标签插入父节点就会执行",el)
    12. }
    13. })
    14. new Vue({
    15. el:'#app',
    16. })
    17. script>

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

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

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

    1. <div id="app">
    2. <div v-msg="red">温馨提示div>
    3. 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 ,也即是绑定的内容,下面来看一下:

    1. "app">
    2. <div v-msg=" 'red' ">温馨提示div>
  • Vue.directive("msg",{
  • // 指令生命周期之一 inserted
  • inserted(el,binding){
  • console.log(binding);
  • console.log("binding.value:",binding.value);
  • ...
  •          通过打印 binding 可以看到关于组件的内容,通过binding。binding.value 能够获取到绑定的值字符串 red,这样就可以来进行操作;

    1. "app">
    2. <div v-msg="'red'">
    3. 温馨提示
    4. 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自定义指令然后以字符串的形式传入颜色:

    1. <div v-msg="'blue'">温馨提示div>
    2. <div v-msg="'green'">温馨提示div>

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

    1. "app">
    2. <div v-msg="mycolor">
    3. 温馨提示
    4. 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周期进行数据更新;下面看编写代码和测试效果:

    1. Vue.directive("msg",{
    2. // 指令生命周期之一 inserted
    3. inserted(el,binding){
    4. el.style.border = "1px solid " + binding.value
    5. },
    6. update(el,binding){
    7. el.style.border = "1px solid " + binding.value
    8. }
    9. })

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


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

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

    测试效果:


    局部自定义指令 - directives使用

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

    1. 编写代码

    1. Vue.component("child",{
    2. template:`
  • `,
  • 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组件的一个路程。

  • 相关阅读:
    武汉星起航:亚马逊卖家如何做好产品的差异化工作?
    前端面试题(Vue与网络相关)
    2022-06-25 C++老八股之 new 的内存用 free 回收有危险
    vue164-自定义指令-全局自定义指令
    qt学习之旅--QToolBar的使用(一)
    苹果曝出两个 iOS 系统 0-Day 漏洞
    归并排序和计数排序
    sql:group by和聚合函数的使用
    猿创征文丨深度学习基于双向LSTM模型完成文本分类任务
    【接口测试】微信小程序接口自动化的实现方案
  • 原文地址:https://blog.csdn.net/weixin_52203618/article/details/127867548