第四十一篇 指令中的VNode

VNode

        前面讲到了自定义指令的引入使用,以及结合封装swiper组件一起进行结合使用,还记在inserted 指令生命周期当中使用的参数吗?第一个参数是可以拿到DOM节点(el),第二个参数是可以拿到使用自定义指令绑定的值(binding),那么它还有第三个参数,就是本篇内容要讲的这个 VNode ,那么当听到这个虚拟DOM,VNode,虚拟节点 和 vdom这些词其实指的是 在Vue中虚拟DOM其实是一个js对象来模拟真实DOM节点跟 diff 算法搭配方便做比对,最后Vue会进行哪些节点能否被复用的复用,不能复用的删除创建,以此达到更好的用户体验。那么下面来简单的自定义一个指令来使用这个三个参数:

<div id="app">
    <div v-custom = "'customVal'">
        {{mytext}}
    </div>
</div>
<script>
    Vue.directive("custom",{
        inserted(el,binding,vnode){
            console.log(el);
            console.log(binding.value);
            console.log(vnode);
        }
    })
    new Vue({
        el:'#app',
        data:{mytext:'自定义指令'}
    })
</script>

        可以查看一下VNode的内容其实它是一个虚拟DOM,虚拟DOM的内容相对真实DOM的内容要少一些,虚拟DOM当中仅有一些必要的属性,那么下面创建一个空div遍历一下真实的DOM: 

         回头看一下这个VNode,当中没有设置key值,所以可以看到的是key值是undefined值;

         在这个div当中还有一个子节点 " {{mytext}} ",没有 "tag",所以它是一个普通的文本节点;

VNode.context

        那么看这些和拿到这个虚拟DOM有啥用?我们知道在Vue中实例化创建之后 —— 才有状态 —— 再有VNode —— 映射真实DOM ,所以这个 VNode 起到关联索引的作用,如果放置在根节点,它就是根组件,放置在里边就是一个子组件,在VNode当中有一个context属性,它能关联到当前组件所在节点的对象,VNode.context 拿到的是组件对象,如果放置在根组件的话,拿到的就是Vue的实例;

         拿到Vue实例有什么用?还记在上一篇内容当中,在inserted指令生命周期中去拿swiperList的数组长度吗?this.swiperList.length并不能够拿到,this的指向是window对象,我们是通过指令绑定的一个对象,通过这个对象的传过来的,那么现在通过VNode.context能够拿到Vue根组件的实例,不就轻而易举的就访问到根组件中swiperList的数组长度;下面来更改上一回封装swiper获取swiperList.length的方式:(具体内容看上一篇内容

上一篇部分代码:(this指向)

<!-- v-swiper绑定的是对象 -->
...
    <div v-swiper=" { current : index , length : swiperList.length } "> ... </div>
..

<script>
    Vue.diretive("swiper",{
        inserted(el,binding){
            // 通过 binding.value.length 拿到 swiperList.length
            console.log(binding.value.length);    // 输出3
        }
    })
    new Vue({ el:'#app',data:{ swiperList:[] },mounted(){ // 赋值swiperList数组三条数据 } })
<script>

修改代码:

<!-- v-swiper绑定的是对象 -->
...
    <div v-swiper="index"> ... </div>
..

<script>
    Vue.diretive("swiper",{
        inserted(el,binding,vnode){
            // 通过 vnode.context 
            console.log(vnode.context.swiperList.length);    // 输出3
        }
    })
    new Vue({ el:'#app',data:{ swiperList:[] },mounted(){ // 赋值swiperList数组三条数据 } })
<script>

        当然如果是封装的话还是需要注意这个,虽然通过vnode.context可以拿到swiperList.length,但它内部是非常依赖外部的状态,如果使用者用到不是swiperList存放数据的话,通过vnode.content.swiperList.length 具有强关联和强耦合,自己使用的话无可厚非。

小知识 - 指令相关周期

常用的 inserted 和 update ,如果内容相同,可以使用函数(function)进行简写;

bind : 只调用一次,指令第一次绑定到元素时调用,在这里可以进行一次性的初始化设置;

inserted : 被绑定元素插入父节点时调用(仅能保证父节点存在,但不一定已被插入到文档中);

update : 所有组件的VNode更行时调用,但是可能发生发生在其子VNode更新之前.指令的值可能发生了改变,也可能没有,但是通过比较更新前后的值来忽略不必要的模板更新;

componentUpdated : 指令所在组件的VNode及其子VNode(children)全部更新后调用;

upbind : 只调用一次,指令与元素解绑时调用;

        那么本篇的内容就到此结束,感谢大家的支持!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

灵魂学者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值