首页 > 其他 > 详细

Vue插槽:slot、slot-scope、v-slot

时间:2019-10-26 16:08:08      阅读:106      评论:0      收藏:0      [点我收藏+]

前言:v-slot 指令自 2.6.0 起被引入,提供更好的支持 slot 和 slot-scope 特性的 API 替代方案。在接下来所有的 2.x 版本中 slot 和 slot-scope 特性仍会被支持,但已经被官方废弃且不会出现在 Vue 3 中。

slot(已废弃)

①内容:假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是slot分发负责的活

②默认情况下,该组件起始标签和结束标签之间的任何内容都会被抛弃

//父组件
<template>
    <div id="app">
        <son>我想显示点内容</son>
    </div>
</template>

//子组件
<template>
    <div>
        <span>我是子组件</span>
    </div>
</template>

技术分享图片

③单个slot:当父组件需要显示一些东西在子组件里时,只需要将这个<slot>放置于子组件想要显示的地方即可,若没有name,则为默认插槽(匿名插槽),一个不带name<slot>出口会带有隐含的名字“default”。

//父组件
<template>
    <div id="app">
        <son>
       <div>我显示出来了</div>
     </son> </div> </template> //子组件 <template> <div> <p><slot></slot></p> <p>我是子组件</p> </div> </template>

上述代码中父组件等同于下面的代码,两者之间的区别是是否将隐含的“default”写出来

//父组件
<template>
    <div id="app">
        <son>
            <div slot="default">我显示出来了</div>
        </son>
    </div>
</template>

技术分享图片

④多个slot:当需要多个插槽显示在不同的地方时,需要给每个插槽加上一个name,并且父组件内加上"slot=name",使两者之间具有有关联性,这就是具名插槽

//父组件
<template>
    <div id="app">
        <son>
            <div slot="slotOne">我是插槽一</div>
            <div slot="slotTwo">我是插槽二</div>
            <div slot="slotThree">我是插槽三</div>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p><slot name="slotOne"></slot></p>
        <p><slot name="slotTwo"></slot></p>
        <p class="content">我是子组件</p>
        <p><slot name="slotThree"></slot></p>
    </div>
</template>

注:多个插槽也能有且最多只能一个默认插槽

⑤当没有对应插槽的name时

1)插槽里没有默认的内容,则会什么的都不输出

//父组件
<template>
    <div id="app">
        <son>
            <div>我想插入进去</div>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p class="content">我是子组件</p>
        <p><slot name="slotOne"></slot></p>
    </div>
</template>

技术分享图片

 2)插槽内有默认内容,则会直接输出插槽内的内容

//父组件
<template>
    <div id="app">
        <son>
            <div>我想插入进去</div>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p class="content">我是子组件</p>
        <p><slot name="slotOne">没有对应name时,我会显示</slot></p>
    </div>
</template>

技术分享图片

⑥当具名插槽和默认插槽混合使用的时候,任何没有包裹slot(或者slot="default")的都将视为默认插槽的内容,对于包裹相同slot值的标签会渲染在同一个位置

//父组件
<template>
    <div id="app">
        <son>
        <div>匿名插槽第一段内容</div>
        <div slot="slotOne">相同具名一</div>
        <div>匿名插槽第二段内容</div>
        <div slot="slotOne">相同具名二</div>
        匿名插槽第三段内容
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p style="border:1px solid #0ff"><slot></slot></p>
        <p style="border:1px solid #f00"><slot name="slotOne"></slot></p>
    </div>
</template>

技术分享图片

slot-scope(已废弃)

本文所有作用域插槽,子组件里news的数据

<script>
export default {
    name: "name",
    data(){
        return{
            news:[
                十九届四中全会28日至31日在京召开,
                珍爱和平团结合作 构建人类命运共同体,
                法治是最好的营商环境,
                夯实优化营商环境的法治基石,
                中国营商环境全球排名再前进15名!
            ],
        }
    }
}
</script>

①作用域插槽或者说是一个带数据的插槽

//父组件
<template>
    <div id="app">
        <son>
            <template slot="news" slot-scope="newsData">
                <ul>
                    <li v-for="(item,index) in newsData.newsList" :key="index">{{item}}</li>
                </ul>
            </template>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p class="content">我是子组件</p>
        <p><slot name="news" :newsList = ‘news‘></slot></p>
    </div>
</template>

技术分享图片 

这里有小坑:

1)这里的 slot-scope 声明了被接收的 prop 对象会作为 newData 变量存在于 <template> 作用域中。你可以像命名 JavaScript 函数参数一样随意命名 newData 。

2)这时的newData数据结构为: 

newsData:{
    newsList:[
        十九届四中全会28日至31日在京召开,
        珍爱和平团结合作 构建人类命运共同体,
        法治是最好的营商环境,
        夯实优化营商环境的法治基石,
        中国营商环境全球排名再前进15名!
    ]
}

3)slot-scope 特性也可以直接用于非 <template> 元素 

<template>
    <div id="app">
        <son>
            <div slot="news" slot-scope="newsData">
                <ul>
                    <li v-for="(item,index) in newsData.newsList" :key="index">{{item}}</li>
                </ul>
            </div>
        </son>
    </div>
</template>

②slot-scope接收到的值也可以使用ES6解构

<template>
  <div id="app">
    <son>
      <div slot="news" slot-scope="{news}">
        <ul>
          <li v-for="(item,index) in news" :key="index">{{item}}</li>
        </ul>
      </div>
    </son>
  </div>
</template>

v-slot

重点来了,v-slot是 v2.6.0 引入的新的指令,目的是为了更好的支持slot、slot-scope的特性(其实就是把两个统一起来),新人上位,老人就应该退居幕后,并辅佐一段时间,所以slot、slot-scope在v2.6.0正式废弃(后续的2.x版本依旧支持,但不推荐),在将来的v3.x版本中正式废除(就是3.x版本不支持不能用了)

①默认插槽写法和以前没什么变化,v-slot主要针对具名插槽、作用域插槽

②具名插槽,v-slot:name

//父组件
<template>
    <div id="app">
        <son>
            <template v-slot:slotOne>我想显示一点内容</template>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p><slot name="slotOne"></slot></p>
    </div>
</template>

这里有小坑

1)除独占默认插槽的缩写语法外,v-slot 只能添加在一个 <template> 上

③作用域插槽,v-slot:name = customName

绑定在 <slot> 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字

//父组件
<template>
    <div id="app">
        <son>
            <template v-slot:news = "newsData">
                <ul>
                    <li v-for="(item,index) in newsData.newsList" :key="index">
                        {{index}}、{{item}}
                    </li>
                </ul>
            </template>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p><slot name="news" :newsList = news></slot></p>
    </div>
</template>

在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 newsData,但你也可以使用任意你喜欢的名字。

④作用域插槽支持ES6解构

将上述例子中父组件改一下

<template>
    <div id="app">
        <son>
            <template v-slot:news = "{newsList}">
                <ul>
                    <li v-for="(item,index) in newsList" :key="index">
                        {{index}}、{{item}}
                    </li>
                </ul>
            </template>
        </son>
    </div>
</template>

⑤独占默认插槽的缩写语法

当子组件内只有默认插槽时,组件的标签可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上

//父组件
<template>
    <div id="app">
        <son v-slot="{news}">
            <ul>
                <li v-for="(item,index) in news" :key="index">
                    {{item}}
                </li>
            </ul>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p><slot :news="news"></slot></p>
    </div>
</template>

这里有小坑

1)当子组件内只有默认插槽时,可以省略default,写作:v-slot = customName

2)当子组件内只有默认插槽时,如果v-slot也准备使用缩写时(#),default不能被省略,写作:#default = customName

⑥独占默认插槽的缩写语法不能与具名插槽混合使用

//父组件
<template>
    <div id="app">
        <son v-slot="{news}">
            <ul>
                <li v-for="(item,index) in news" :key="index">
                    {{item}}
                </li>
            </ul>
            <div v-slot:mixinSlot>默认插槽的缩写语法和具名插槽混用,导致作用域不明确</div>
        </son>
    </div>
</template>

//子组件
<template>
    <div>
        <p><slot :news="news"></slot></p>
        <p><slot name="mixinSlot"></slot></p>
    </div>
</template>

技术分享图片

⑦动态插槽名,用来来定义动态的插槽名

在v2.6.0版本中新增动态参数,可以用方括号([])括起来的 JavaScript 表达式作为一个指令的参数,动态参数我将在另一篇文章叙述

//父组件
<template>
    <div id="app">
        <son>
            <template v-slot:[slotName] ={ news }>
                <ul>
                    <li v-for="(item,index) in news" :key="index">{{item}}</li>
                </ul>
            </template>
        </son>
    </div>
</template>

<script>
import son from "./components/son";

export default {
    name: "App",
    components: {
        son
    },
    data(){
        return{
            isOK: false
        }
    },
    computed: {
        slotName(){
            return this.isOK ? slot1 : slot2
        }
    },
};
</script>

//子组件
<template>
    <div>
        <slot name="slot1" :news=news></slot>
        <slot name="slot2" :news=news2></slot>
    </div>
</template>

<script>
export default {
    name: "name",
    data() {
        return {
            news: [
                "十九届四中全会28日至31日在京召开",
                "珍爱和平团结合作 构建人类命运共同体",
                "法治是最好的营商环境",
                "夯实优化营商环境的法治基石",
                "中国营商环境全球排名再前进15名!"
            ],
            news2: [
                27省份前三季度GDP出炉 16省份GDP增速跑赢全国,
                新航季来了!这些航班将飞大兴机场,坐飞机别走错,
                北方回暖南方雨连绵 江南等多地气温将创新低,
                水润民心 脱贫路上“领头雁”  钟声,
                看看第六届世界互联网大会国际组织说了啥
            ]
        };
    }
};
</script>

印象中,好像没什么地方需要用到动态插槽名,如果有大大遇到需要使用,还请留言,非常感谢,上述栗子如果用v-if,语义更明朗

技术分享图片

⑧v-slot缩写为:#

具名插槽缩写为:#name

作用域插槽缩写

1)当为匿名作用域插槽时:#default = customName(#=customName这种写法为报错)

2)当为具名作用域插槽时:#name = customName

Vue插槽:slot、slot-scope、v-slot

原文:https://www.cnblogs.com/bulici/p/11733840.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!