slot插槽与slot作用域插槽的区别

目录

 

前言

slot插槽的概念

区别


前言

这段之间在看vue的底层代码,所以借助vue-template-compiler看一下底层编译出来的数据来对比slot插槽的差异

slot插槽的概念

官方说明

 
20315386-025523f560017cce.png
 

 

个人理解
插槽就是在子组件里做定制化内容,当一个复用的组件内有一部分需要针对不同的场景有所差异,且无规律可循时,我们就可以使用<slot></slot>让父组件自定义内容。
这种时候又可以分为两个场景:

  1. 内容与子组件内的数据无关
  2. 内容与子组件内的数据有关
    前者使用普通插槽,后者使用作用域插槽,作用域插槽的作用就是拿到子组件的数据
    具体介绍及使用可参考官方文档
    https://cn.vuejs.org/v2/guide/components-slots.html

区别

普通插槽在父组件初始化期间会编译成文本子节点存起来,在子组件渲染的时候直接将插槽替换成父组件里渲染的节点
作用域插槽在父组件初始化期间会编译成一个函数,在子组件初始化的时候执行这个函数生成vnode再进行渲染

下面会针对两种插槽看用vue模板编译器对模板编译后的render函数
了解一下vue的渲染函数的缩写

 
20315386-4b394a2e84645529.png
 

 

 

 
20315386-97a9569b785fe709.png
 


_c(createElement),_t(renderSlot),_v(createTextVNode)是下面会常看到的

 

普通插槽

r1为子组件,r2为父组件

let r1 = VueTemplateCompiler.compile('
    <div>
        <span>hello</span>
        <slot name="header">name</slot>
    </div>
');
let r2 = VueTemplateCompiler.compile('
    <div>
        <span>hello</span>
        <div slot="header">name</div>
    </div>
');

先看父组件渲染结果

r2.render=
'with(this){
    return _c(\'div\',[
        _c(\'span\',[
            _v("hello")
        ]),
        _c(\'div\',{     //在编译时将插槽已经编译成虚拟节点存进[_v("name")]
            attrs:{
                "slot":"header"
            },
            slot:"header"
        },[_v("name")])
    ])
}'

下面是子组件的render函数

r1.render=
'with(this){
    return _c(\'div\',[
        _c(\'span\',[
              _v("hello")
        ]),
        _t("header",[_v("name")])   //在渲染时将header替换成父组件编译完成的[_v("name")]
    ],2)
}'

可以看出父组件在编译组件时就将slot插槽内容调用_c方法编译成节点了,并用_v("name")将文件节点保存,当子组件初始化时,会调_t()方法渲染插槽,会先去父组件中寻找名为"header"的插槽,将"header"替换成_v("name"),渲染过程就是将vnode渲染成真实Dom

作用域插槽

r3为子组件,r4为父组件

let r3 = VueTemplateCompiler.compile('
    <div>
        <span>hello</span>
        <slot name="footer" a="1"></slot>
    </div>
');

let r4 = VueTemplateCompiler.compile('
    <div>
        <span>hello</span>
        <div slot="footer" slot-scope="msg">{{msg.a}}</div>
    </div>
');

先看父组件

r4.render=
'with(this){
    return _c(\'div\',{
        scopedSlots:  
            _u([{
                  key:"footer",
                  fn:function(msg){  //将插槽编译成函数
                      return _c(\'div\',{},[_v(_s(msg.a))])
                  }
            }])
        },
        [_c(\'span\',[_v("hello")])]
  )
}'

子组件

r3.render=
'with(this){
      return _c(\'div\',[
                _c(\'span\',[_v("hello")]),
                _t("footer",null,{a:"1"})
    ],2)
}'

父组件编译时将插槽编译成函数存进数组里,子组件初始化时会根据插槽名"footer"去父组件里找key"footer"的函数并执行,然后生成vnode进行渲染

在vue2.6.0以后,旧版的slot、slot-scope的使用就被废弃了,但是还可以用,推荐统一使用v-slot

 

 
20315386-152349237efb3a39.png
 

 

我用作用域插槽用的最多的还是在使用组件库的时候,可见大型组件库内部留了很多插槽,便于客户去定制化使用
我们在封装组件的时候也可以去考虑使用哪种插槽能符合更多场景,提高复用性

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值