关于Vue自定义指令的一些讨论

关于Vue自定义指令的一些讨论(实现v-show效果)

平时学习时做个记录,也分享给大家,各位大佬觉得不好的地方希望指正

  1. 局部自定义组件的定义

钩子函数

一个指令定义对象可以提供如下几个钩子函数 (均为可选):

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="app">
        <button @click="btn">点击显示隐藏</button>
        <h1 v-demo="flag">这是一个标题</h1>
    </div>
    <script>
        new Vue({
            el: "#app",
            data: {
                flag: true
            },
            methods: {
                btn() {
                    this.flag = !this.flag
                }
            },
            //局部自定义的指令通过directives进行定义
            directives: {
            	//directives里面第一个对象就是我们的自定义组件的名称,比如这里就是demo
                demo: {
                	//demo里面可以有三个钩子函数,一般我们平时用的话就如下两个用的多,以上有对三个钩子函数的官网释义
                    inserted(el, binding) {
                    	//钩子函数它可以有4个形参,在下面也给大家贴出了官网释义4个参数分别是什么
                        if (binding.value == true) {
                            el.style.display = "block"
                        } else {
                            el.style.display = "none"
                        }
                    },
                    // 进行状态更新
                    update(el, binding) {
                        if (binding.value == true) {
                            el.style.display = "block"
                        } else {
                            el.style.display = "none"
                        }
                    }
                }
            }
        })
    </script>
</body>
</html>

钩子函数参数

el:指令所绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含以下 property:

  1. name:指令名,不包括 v- 前缀。
  2. value:指令的绑定值,例如:v-my-directive=“1 + 1” 中,绑定值为 2。
    oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
  3. expression:字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
  4. arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
  5. modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true,
    bar: true }。

vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

  1. 全局自定义指令
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../vue.js"></script>
</head>
<body>
    <div id="app">
        <button @click="btn">点击显示隐藏</button>
        <h1 v-demo="flag">这是一个标题</h1>
    </div>
    <script>
    //全局自定义指令通过directive来定义,局部自定义组件是使用directives,注意区分
        Vue.directive("demo",{
        	//这里注释掉inserted是因为学习过程中做了个小测试,下面进行分享
            // inserted(el,binding){
            //     if(binding.value==true){
            //         el.style.display="block"
            //     }else{
            //         el.style.display="none"
            //     }
            // },
            // 进行状态更新
            update(el,binding){
                if(binding.value==true){
                    el.style.display="block"
                }else{
                    el.style.display="none"
                }
            }
        })
        new Vue({
            el:"#app",
            data:{
                flag:false
            },
            methods:{
                btn(){
                    this.flag = !this.flag
                }
            }
        })
    </script>
</body>
</html>
  1. 关于inserted钩子函数
    下面给大家分享一下以上为什么会有想法把inserted这个钩子函数注销进行测试:

因为在学习过程中大家有想法说,我把inserted钩子函数删除,只用update钩子函数也可以实现相同的效果,那么是否真的是这样呢?

我们先看写inserted钩子函数运行后的结果以及dom结构

  • 运行结果
    运行后的样子
  • dom结构
    dom结构
    我们可以看到inserted写上效果是完全没有问题的
    下面是不写inserted钩子函数并且flag为true的运行结果以及dom结构
  • 运行结果
    在这里插入图片描述
  • dom结构
    在这里插入图片描述
    我们会发现运行结果都是相同的,但是样式发生了改变,但是为什么会依然能实现呢?
    再进行对比,这次是我们上面代码,也就是不写inserted钩子函数并且flag为false的情况
  • 运行结果
    在这里插入图片描述
  • dom结构
    在这里插入图片描述
    好了,两个问题出现了,我们明明定义的是false对不对,那为什么刚运行他就是显示的呢?
    为什么我们第一次点击没有效果,第二次点击功能就正常了呢?

其实问题很简单,我们前面第一种情况会显示是很正常的,因为项目刚运行的时候,我们的inserted就进行了插入,所以不管我们flag是false还是true都会执行处相应的结果,第二种情况我们就发现了问题,我们没有写inserted钩子函数,但是功能正常,这个时候我们注意到的dom结构上好像少了点什么,带着问题走进第三种情况,样式依旧没有,但是除了一个小问题,第一次点击没有效果,问题就处在了inserted钩子函数身上,我们刚运行事,代码从上往下执行,并没有读取到inserted钩子函数,继续往下读遇到了update钩子函数,这个时候update是不会执行的,因为update只会在发生改变的时候进行更新,而这里我们并没有改变,也就是说刚执行时,我们的自定义指令并没有生效,h1标签也是一个正常显示的状态,这里也就可以解释为什么flag为false时依然会显示,而当我们点击时,flag的状态发生了改变,第二种情况本身flag为true,并且h1本来就是显示的,所以点击后update进行了更新,所以功能正常,但是第三种情况,我们本身就是显示的,自定义指令并没有生效,flag为false,点击之后进行了更新,自定义指令生效了,但是他flag这个时候为true,所以我们第一次点击没有效果,也就可以解释的通了,当我们继续点击的时候功能也就不会有问题了。

总结:inserted会在代码一执行就会把状态加上,如果不写,我们刚进去的时候状态不会有,也就是自定义指令不会生效

初次写博客,不当之处还请各位大佬指正

猜你喜欢

转载自blog.csdn.net/qq_39172655/article/details/107471775