Vue之深入了解插槽—slot, slot-scope, v-slot, v-slot:[name]=slotProps, $slots, $scopedSlots

作者 : 开心源码 本文共3652个字,预计阅读时间需要10分钟 发布时间: 2022-05-13 共232人阅读
Vue 2.6.0 以前Vue 2.6.0 以后
具名插槽 slot具名插槽 v-slot
作用域插槽 slot-scope = slotProps作用域插槽 v-slot: [name] = slotProps

这里我们要探讨的不是怎样用,而是比较少有探索的 slot, slot-scope 以及 v-slot, v-slot:[name] = slotProps$slots, $scopedSlots 的关系,一般在应用中不涉及渲染函数,很少用得到$slots$scopedSlots,但是在深入了解插槽的实现和二次封装 UI库 的时候即可能用得上了。

一、 slotslot-scope$slots, $scopedSlots 的关系

1. 无作用域插槽

HTML

<div id="parent-template">    <child>        <!--此处是待分发的内容-->        <p slot="header">header</p>        <p slot="footer">footer</p>        <p>default</p>    </child></div><template id="child-template">     <div>        <slot name="header"></slot>        <slot>默认分发处</slot>        <slot name="footer"></slot>    </div></template>

JS

// 注册子组件Vue.component("child", {    template:"#child-template",  mounted() {    console.log('$slots',this.$slots)    console.log('$scopedSlots',this.$scopedSlots)  }});// 初始化父组件new Vue({    el: "#parent-template"});

Console 输出

v2.5.22无作用域插槽.pngv2.6.10无作用域插槽.png

这是一个常用的插槽模板,从这个结果中可以看出v2.6.0以前,slot 和 slot-scope是分开的 ;

v2.6.0以前父组件没有调用 slot-scope 时, $scopedSlots 里面为空 ;

v2.6.0以后 $scopedSlots 里的具名值和 $slots 具名值是逐个对应的。

2. 有作用域插槽

HTML

<div id="parent-template">    <child>        <!--此处是待分发的内容-->        <p slot="header" slot-scope="{header}">{{ header }}</p>        <p slot="footer">footer</p>        <p>default</p>    </child></div><template id="child-template">     <div>        <slot name="header" v-bind:header="'header'"></slot>        <slot>默认分发处</slot>        <slot name="footer" v-bind:footer="'footer'"></slot>    </div></template>

v2.5.22有作用域插槽.pngv2.6.10有作用域插槽

v2.6.0以前,在父组件中’header’具名插槽中调用了slot-scope后,$scopedSlots 中出现了‘header’为key的function, $slots 中‘header’为key的VNode不见了;

v2.6.0以后,在父组件中’header’具名插槽中调用了slot-scope后,$scopedSlots 中没有变化, $slots 中‘header’为key的VNode不见了。

3. 屡次调用同一个具名插槽

HTML

<div id="parent-template">    <child>        <!--此处是待分发的内容-->        <p slot="header">header</p>    <div slot="header">header1</div>        <p slot="footer">footer</p>        <p>default</p>    </child></div><template id="child-template">     <div>        <slot name="header" v-bind:header="'header'"></slot>        <slot>默认分发处</slot>        <slot name="footer" v-bind:footer="'footer'"></slot>    </div></template>

Console 输出

v2.5.22 屡次调用同一个具名插槽.pngv2.6.·0 屡次调用同一个具名插槽.png

从输出结果可以看出老式写法在v2.6.0以前和以后都能在$slots里有两个header的具名插槽内容,这与后面新式写法就有不同。

二、v-slot, v-slot:[name]=slotProps$slots, $scopedSlots 的关系

1. 无作用域插槽

HTML

<div id="parent-template">  <child>  <!--此处是待分发的内容-->    <template v-slot:header>      <p>{{ header }}</p>    </template>    <template v-slot:footer>      <p>footer</p>    </template>    <template v-slot:default>      <p>default</p>    </template>  </child></div><template id="child-template">     <div>        <slot name="header"></slot>        <slot>默认分发处</slot>        <slot name="footer"></slot>    </div></template>

Console输出

v2.6.10 具名插槽.png

从输出可以看出,新式写法在v2.6.0版本后,default中tag 为 undfined的元素没有了,并且$slots中的内容是后面塞进去的,$scopedSlots一开始就有。

2. 有作用域插槽

HTML

<div id="parent-template">  <child>  <!--此处是待分发的内容-->    <template v-slot:header="{header}">      <p>{{ header }}</p>    </template>    <template v-slot:footer>      <p>footer</p>    </template>    <template v-slot:default>      <p>default</p>    </template>  </child></div><template id="child-template">     <div>        <slot name="header" v-bind:header="'header'"></slot>        <slot>默认分发处</slot>        <slot name="footer" v-bind:header="'footer'"></slot>    </div></template>

Console 输出

v2.6.10 作用域插槽.png

这个输出同老式写法在v2.6.0版本后的输出一样,除了一开始$slots里面没有值,是后面塞进去的。

3. 屡次调用同一个具名插槽

HTML

<div id="parent-template">  <child>  <!--此处是待分发的内容-->    <template v-slot:header>      <p>header</p>    </template>    <template v-slot:header>      <p>header1</p>    </template>    <template v-slot:footer>      <p>footer</p>    </template>    <template v-slot:default>      <p>default</p>    </template>  </child></div><template id="child-template">     <div>        <slot name="header" v-bind:header="'header'"></slot>        <slot>默认分发处</slot>        <slot name="footer" v-bind:header="'footer'"></slot>    </div></template>

Console输出

v2.6.10 屡次使用具名插槽

从输出可以看出,新式写法屡次调用同一个具名插槽,后面的会覆盖前面的,这个和老是写法一个比较大的区别,在更新的时候就要特别注意。

小结

经过上面的实践比照,有以下几点结论:

  1. v2.6.0以后在$slots里可以取到具名key,在$scopedSlots都能取到;
  2. v2.6.0以后v-slot的写法不能屡次使用同名的具名插槽,后面的会覆盖前面的,不会显示两个同名具名插槽的内容;
  3. v2.6.0以后用v-slot的写法,假如在子组件中用$slot,肯定调用watch方法,由于一开始$slots为空,后面才塞入的数据。
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Vue之深入了解插槽—slot, slot-scope, v-slot, v-slot:[name]=slotProps, $slots, $scopedSlots

发表回复