插槽可以分为几点:
- 插槽的内容
- 具名插槽
- 插槽作用域
一.插槽的内容
一句话:插槽内可以是任意内容先看一下下面的代码
<div id="#app">
<child>Hello World</child>
</div>
<script>
Vue.component('child', {
template: `
<div>
<slot></slot>
</div>
`
});
let vm = new Vue({
el: "#app",
data: {}
})
</script>
也就是说,没有插槽的情况下在组件标签内写的内容是不起任何作用的,只有在组件中声明了slot元素后,在组件元素内写的内容就会跑到<slot></slot>中。
二.具名插槽
具名插槽,就是给这个插槽起个名字
例如:在组件中,给三个插槽加上名字,在创建新的组件内,slot属性对应的内容都会和组件中name一一对应,而没有名字的,就是默认插槽。
<parent>
<template slot="header">
this is header
</template>
<template slot="main">
this is main
</template>
<template slot="footer">
this is footer
</template>
</parent>
Vue.component('parent', {
template: `
<div>
<div style="margin-top: 2em;color: red">
<slot name="header"></slot>
</div>
<div style="color: orange ">
<slot name="main"></slot>
</div>
<div style="color: yellow">
<slot name="footer"></slot>
</div>
</div>
});
具名插槽vue 2.6+语法展示(Vue 3支持)
自 2.6.0 起具名插槽有所更新,上面那一种方式在所有的 2.x 版本中 slot仍会被支持,但已经被官方废弃且不会出现在 Vue 3 中。
那我们就把上面的例子用2.6.0的新语法写一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>插槽基本用法了解
</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<child>
<template v-slot:header><!-- 注意和废弃语法slot="header"对比 -->
<div class="header">header</div><!-- v-slot不能直接写在标签上,必须写在template,否则渲染不出来 -->
</template>
<template #footer><!-- 注意和废弃语法slot="footer"对比 -->
<div class="footer">footer</div><!-- v-slot不能直接写在标签上,必须写在template,否则渲染不出来 -->
</template>
</child>
</div>
<script>
Vue.component('child', {
template:`<div>
<slot name="header"></slot>
<p>hello</p>
<slot name=footer></slot>
</div>` // 换成ES6的语法可以换行方便查看
})
var vm = new Vue({
el: "#app"
})
</script>
</body>
</html>
注意:就像v-on:可以缩写成@一样,v-slot:也可以缩写成#,所以v-slot:footer可以缩写成#footer
一个不带 name 的 <slot></slot>会带有隐含的名字name=“default”,父组件传的DOM内容如果不写这种v-slot:header具体告知说要找name="header"的插槽,则就会匹配到<slot></slot>不带name的插槽。
注意 v-slot 只能添加在 <template> 上
插槽作用域
话不多说直接上代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作用域插槽
</title>
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<child>
<template #myname="myScope"><!-- #myname等同于v-slot:myname,等同于2.5具名插槽旧语法slot="myname" -->
<h1>{{myScope.myItem}}</h1>
</template>
<template v-slot="myScope1"><!-- 注意这里是v-slot="myScope1"不是slot="myScope1",要和具名插槽的旧语法区别开 -->
<h2>{{myScope1.myItem}}</h2>
</template>
</child>
</div>
<script>
Vue.component('child', {
data() {
return {
list: [1, 2, 3, 4]
}
},
template: `<div>
<ul>
<slot v-for="item of list"
:myItem=item>
</slot>
<slot name="myname" :myItem=list></slot>
</ul>
</div>`
})
var vm = new Vue({
el: "#app"
})
</script>
</body>
</html>
运行结果:
在上一个例子的基础上需要再解释一下
旧语法slot-scope="myScope"
等同于新语法v-slot="myScope"
,name
默认就是default
#myname="myScope"
是v-slot:myname="myScope"
的简写,而v-slot:myname
是Vue2.5中具名插槽slot="myname"
的简写,#myname="myScope"
就是匹配name
为myname
的插槽slot
,并取别名为"myScope"
,可以通过"myScope"去操作slot上绑定的数据
v-slot="myScope1"等同于v-slot:default=“myScope1”,而插槽<slot>不写name则默认name=“default”,所以也可以缩写成#default=“myScope1”。匹配默认插槽不能直接#,至少加上#default,否则就会如下报错
记得这个标签上的name一定要小写!否则渲染不出来。
有人会问,应该是数组在前,列表在后呀,记得渲染顺序以插槽的位置为准,不是根据父作用域的template顺序判断,这里子组件的第一个绑定的是for循环的每条数据,第二个绑定的才是list!