Vue-Slot的使用和理解

Slot

Slot=>内容分发,占位元素

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。Slot分发的内容,作用域是在父组件上

1.Vue2.6版本前的旧特性用法

1.1不具名slot

父组件内使用子组件

<children>
    <p>我是第一行</p>
    <p>我是第二行</p>
</children>

子组件模板内容

<div>
    <p>template div 内容</p> 
    <!-- <slot>slot标签内的内容</slot>slot外div内的内容 -->
</div>

渲染过程: 模板内容直接替换childre中的内容

<div>
    <p>template div p 内容</p>
</div>

接上 启用slot后的渲染结果

<div>
    <p>template div 内容</p>
    <p>我是第一行</p>
    <p>我是第二行</p>
    <!--复制被调用子组件内的内容并替换<slot></slot>自身-->
    slot外div内的内容<!--该内容按从上到下被渲染-->      
</div>

渲染过程: 按子组件模板从上至下渲染,先将<p>template div 内容</p>渲染出来,紧接着读取到slot标签立即复制被调用子组件内的内容并替换<slot></slot>自身,然后渲染子组件模版内剩余

1.2具名slot

父组件内使用子组件

<children>
    <p>我是第一行</p>
    <p>我是第二行</p>
    <slot>第一个slot</slot>
    <slot>第二个slot</slot>
    <h2 slot="header">头部在这</h2>
    <p>中间在这</p>
    <div slot="footer">
        <div>底部在这</div>
    </div>
</children>

子组件模板内容

<div>
    <slot></slot>
    <h2 slot="header">h2 slot=header</h2><!--不报错,应该被认为常规元素,会被渲染到不具名slot区域-->
    <slot name="header"></slot><!--在父组件中搜查匹配 带有名叫"header"slot的元素并复制替换本处元素-->  
    <slot name="footer"></slot><!--在父组件中搜查匹配 带有名叫"footer"slot的元素并复制替换本处元素-->  
</div>

渲染成:

<div>
    <p>我是第一行</p>
    <p>我是第二行</p> 第一个slot 第二个slot <p>中间在这</p>
    <h2 slot="header">h2 slot=header</h2>
    <h2>头部在这</h2>
    <div>
        <div>底部在这</div>
    </div>
</div>

渲染过程:读取到slot标签后将被调用的子组件中没有被具名插槽包裹的内容及子组件模版内的常规内容替换slot标签所在区域并按顺序渲染,读到具名slot则在被调用的子组件中查找与之name对应的内容复制替换对应的具名插槽并渲染

1.3作用域插槽 slot-scope

2.6之前 ==>slot scope=”别名”
在父组件内使用 slot-scope 并使用传入的数据
将<span v-for=”item in aaa.shuju”>{{item}}</span>复制替换子组件的<slot></slot>,并将“shuju”作为receiveData的新属性(类似这个意思),此时receiveData.shuju就等同于子组件中返回的data对象

<template slot-scope="receiveData">
    <div>
    <span v-for="item in receiveData.shuju">{{item}}</span>
   </div>
</template>

在子组件内设定传入的值并在slot上绑定需要传入的值
子组件内

模板:     
<div>
     <slot :shuju="data"></slot>
</div>

其他:

data:function(){
return{
  data:['zhangsan','lisi','wangwu','maliu','qianqi','zhouba']
          }
     }

最终渲染成:

<div>
    <h3>这里是子组件</h3>
    <div>
        <span>zhangsan</span><span>lisi</span><span>wangwu</span><span>maliu</span><span>qianqi</span><span>zhouba</span>
    </div>
</div>

2.Vue2.6版本及以后的新特性用法

2.1 不具名插槽

父组件内使用子组件

<children>
    <template v-slot> <!--此处的v-slot等同于 v-slot:default-->
        <div>
            template v-slot中的内容
        </div>
    </template>
</children>

子组件模板内

<div>
    <slot></slot>     
</div>

最终渲染成:

<div>
     <div>
        template v-slot中的内容
     </div>
</div>

渲染过程基本一致

2.2 具名插槽

2.6新特性 v-slot 只能被用于组件或者模板 上方使用v-slot
父组件内使用子组件

<children>
    <template v-slot:header>
        hahaha
    </template>
    <template v-slot:footer>

        脚在这儿
    </template>
    <template v-slot:header>头部在这</template>
    <!--此处会覆盖上面同名-->
    <p>中间在这</p>
    <template v-slot:footer>
        <!--此处会覆盖上面同名-->
        <div>底部在这</div>
    </template>
</children>

子组件模板内

<div>
    <slot></slot>
    <slot name="header"></slot>
    <slot name="footer"></slot>
</div>

最终渲染成:

<div>
    <p>中间在这</p> 
    头部在这 
    <div>底部在这</div>
</div>

渲染过程基本一致
注意:多个同名具名插后面的覆盖前面的,只会有一个起效!

2.3作用域插槽

v-slot
在父组件内使用 v-slot=”xxx” 并传入的数据

<children>
        <template v-slot:header>
            hahaha
        </template>
        <template v-slot:footer>

            脚在这儿
        </template>
        <template v-slot:header>头部在这</template>
        <!--此处会覆盖上面同名-->
        <p>中间在这</p>
        <template v-slot:footer="receiveData">
            <!--此处会覆盖上面同名-->
            <div>底部在这</div>
            <div>{{receiveData.sendData.firstName}}+{{receiveData.sendData.lastName}}</div>
        </template>
</children>

子组件模板内

<div>
    <slot></slot>
    <slot name="header"></slot>
    <slot name="footer" :sendData="userInfo"></slot>
</div>

最终渲染成:

<div>
    <p>中间在这</p> 
    头部在这 
    <div>底部在这</div>
    <div>Brain+Lu</div>
</div>

渲染过程基本一致

3.理解及结论

默认(后备)内容[一般指子组件模板内的<slot>默认(后备)内容</slot>]生效的情况:在父组件内使用的子组件内不包含可渲染内容的情况下会被渲染出来。
渲染顺序:在父组中被调用的子组件外的内容有线渲染,然后子组件模板内从上至下渲染。
Slot执行过程:子组件的模板把父组件中的内容(<children>内容</children>)选择性复制然后替换本身。
Slot-不具名插槽==>子组件模板内各个<slot></slot>都会把父组件中除具名插槽包裹的其他内容复制一份并替换自身(<slot></slot>)位置
Slot-具名插槽==>子组件模板内各个<slot name=”xxx”></slot>都会把父组件中的与匹配的具名插槽包裹的其他内容复制一份并替换自身(<slot></slot>)位置再渲染
v-slot写法同时存在多个同名具名插槽,写在最后的那个起效
同时存在两种写法的情况下 新写法的渲染优先级更高,不论是否具名都会覆盖掉就写法

<template v-slot:footer>
     template v-slot
</template>
<p slot="footer">slot=footer</p>   <!--此处不会被渲染,不论写在v-slot之前还是之后-->

目前还未应用于实际场景,听闻Element的table组件和Button组件似乎有用到slot,暂未探究,有兴趣的小伙伴可以去看看;有实际应用也可告诉我。
注:结论等均是感性认知,不一定是正确的,只是方便理解(也许只是自己)

    原文作者:Forever_ward
    原文地址: https://segmentfault.com/a/1190000018971908
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞