插槽分类:具名插槽与作用域插槽。在新版中(2.6.0)统一都叫v-slot指令,老版中称之为slot与slot-scope。
插槽的理解:在子组件中,插槽本身提供一个占位符,里面的内容将来会被替换(由外界,即父组件决定,如果外界不提供那就显示默认的),如果很多的<slot></slot>标签外界怎么区分?如何准确找到要替换的内容?那么就由slot的name属性来起到标志作用。
1. 新版用法:
- 具名插槽与匿名插槽:前者带name属性,后者不带name属性,新版用法如下:
//父组件html中
<div id="app">
<childSlot>
<template v-slot:footer>
<p>底部</p>
</template>
<p>这并不会被渲染出来</p>
<template v-slot:default>
<p>这个默认会被渲染出来,v-slot一般只用在 template标签里面,'v-slot:default' 可以被省略掉</p>
</template>
<template v-slot:header>
<!--可以尝试一下在这注释h1标签-->
<h1>头部</h1>
</template>
</childSlot>
</div>
v-slot一般只用在 template标签里面,'v-slot:default' 可以被省略掉
//子组件html中
<div class="childSlot">
<h2>子组件的显示</h2>
<div class="container">
<header>
<slot name="header">如果父组件注释掉h1标签,那我会渲染出来,否则会被替换掉</slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</div>
- 作用域插槽:插槽内容(父组件)能够访问子组件中才有的数据。
原理:将你的插槽内容包裹在一个拥有单个参数的函数里:
function (slotProps) {
// 插槽内容
}
- 这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下(单文件组件或现代浏览器),我们可以解构出来。
- 具名插槽也支持缩写的语法:"v-slot:"可以被省略掉,替换为"#",写法见下图:
- v-slot 上,也支持动态的插槽名(代码中已省略)
//父组件原来的代码上,新加一点点东西
<childSlot>
<template v-slot:footer="slotProps">
<p>底部</p>
<!--<p>slotProps是自定义的,使用的时候</p>-->
<p>{{slotProps.msgInfo.age}}</p>
</template>
<!-- <template #footer="slotProps">
<p>底部</p>
<p>这是缩写的用法:'v-slot:'可以被省略掉</p>
<p>{{slotProps.msgInfo.age}}</p>
</template>-->
<!-- <template v-slot:footer="{msgInfo}">
<p>底部</p>
<p>可以尝试打开我看看,这是第二种方法解构:解构的时候其实也是支持重新命名的,具体参考es6语法</p>
<p>{{msgInfo.age}}</p>
</template>-->
<p>这并不会被渲染出来</p>
<template v-slot:default> <p>这个默认会被渲染出来,v-slot一般只用在 template标签里面,'v-slot:default' 可以被省略掉</p></template>
<template v-slot:header>
<!--可以尝试一下在这注释h1标签-->
<!--<h1>头部</h1>-->
</template>
</childSlot>
下面子组件中需要被访问的数据被当成了slot标签的属性绑定上,让父组件访问到
//子组件vue
<div class="childSlot">
<h2>子组件的显示</h2>
<div class="container">
<header>
<slot name="header">如果父组件注释掉h1标签,那我会渲染出来,否则会被替换掉</slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer" v-bind:msgInfo="msg"></slot>
</footer>
</div>
</div>
<script>
export default {
name: "childSlot",
data(){
return{
msg:{
userName:'张三',
age:18
}
}
}
}
</script>
- 独占默认插槽的写法(个人不推荐这种写法,了解就好啦,):
//父组件
<childSlot v-slot:default="slotProps">
<!-- <template v-slot:header>
<h1>头部</h1>
</template>-->
<p>把上面的打开会报错,因为这会导致作用域不明确</p>
{{ slotProps.msgInfo.age }}
</childSlot>
<div class="childSlot">
<h2>子组件的显示</h2>
<div class="container">
<header>
<slot name="header">如果父组件注释掉h1标签,那我会渲染出来,否则会被替换掉</slot>
</header>
<main>
<slot v-bind:msgInfo="msg"></slot>
</main>
</div>
</div>
<script>
export default {
name: "childSlot",
data(){
return{
msg:{
userName:'张三',
age:18
}
}
}
}
</script>
2. 旧版用法:
旧版主要存在两个API:slot和slot-scope,这两个语法在2.6以后的版本也是支持的,但是在3.0以后不再支持了。
slot的位置:
//直接放在父组件的template标签中(普通标签也是ok的)
<template slot="header">
<h1>头部</h1>
</template>
<template slot="footer">
<p>底部</p>
</template>
<div slot="footer">slot放在普通div或者p标签也是可以的</div>
slot-scope的作用:
//在父组件中被当做特殊的attribute,用来接受插槽的prop
<template slot-scope="slotProps">
{{ slotProps.msg }}---slotProps可以自定义
</template>
<span slot-scope="{ msg }">
{{ msg }} ---可以用在非template的其它标签中,当然被挂载的属性也可以直接被解构出来
</span>