• 第四十一篇 指令中的VNode


    VNode

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

    1. <div id="app">
    2. <div v-custom = "'customVal'">
    3. {{mytext}}
    4. div>
    5. div>
    6. <script>
    7. Vue.directive("custom",{
    8. inserted(el,binding,vnode){
    9. console.log(el);
    10. console.log(binding.value);
    11. console.log(vnode);
    12. }
    13. })
    14. new Vue({
    15. el:'#app',
    16. data:{mytext:'自定义指令'}
    17. })
    18. 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指向)

    1. ...
    2. <div v-swiper=" { current : index , length : swiperList.length } "> ... div>
    3. ..
    4. <script>
    5. Vue.diretive("swiper",{
    6. inserted(el,binding){
    7. // 通过 binding.value.length 拿到 swiperList.length
    8. console.log(binding.value.length); // 输出3
    9. }
    10. })
    11. new Vue({ el:'#app',data:{ swiperList:[] },mounted(){ // 赋值swiperList数组三条数据 } })