默认插槽
当类似结构的组件需要插入不同元素的时候,可以使用插槽。
默认插槽很简单,只需要在App中将组件写为双标签格式,并在标签内写入需要插入的标签或者内容,然后再组件中需要插入的位置写上slot标签,slot标签内可以写无插入默认显示的内容,当然不写也是可以的。
MySlot组件:
<template>
<div class="slotBox">
<h1>{{ title }}</h1>
<!--slot的位置-->
<slot></slot>
</div>
</template>
<script>
export default {
name: "MyList",
props: ["title"],
};
</script>
<style scoped>
h1 {
background-color: aqua;
text-align: center;
}
.slotBox {
background-color: pink;
width: 200px;
height: 300px;
}
img,
video {
width: 100%;
}
</style>
App组件
<template>
<div class="container">
<MySlot title="美食">
<!--将需要插入的内容写在标签内部-->
<img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" />
</MySlot>
<MySlot title="游戏">
<ul>
<li v-for="(game, index) in games" :key="index">{{ game }}</li>
</ul>
</MySlot>
<MySlot title="电影">
<video
controls
src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
></video>
</MySlot>
</div>
</template>
<script>
import MySlot from "./components/MySlot.vue";
export default {
components: { MySlot },
name: "App",
data() {
return {
foods: ["梨子", "饮料", "其他"],
games: ["冒险岛", "dota2", "魔兽世界"],
movies: ["权利的游戏", "魔法少女小圆", "斩赤红之瞳"],
};
},
};
</script>
<style scoped>
.container {
display: flex;
justify-content: space-around;
}
</style>
具名插槽
可以给slot标签加上name属性,而相应的组件加上slot属性,从而实现精准填充。并且在用template的时候,slot="xxx"可以替换为v-slot:xxx,但是一般都用原来的写法,因为只有在标签为template的时候才能使用。
MySlot组件:
<template>
<div class="slotBox">
<h1>{{ title }}</h1>
<slot name="center"></slot>
<slot name="footer"></slot>
</div>
</template>
<script>
export default {
name: "MyList",
props: ["title"],
};
</script>
<style scoped>
h1 {
background-color: aqua;
text-align: center;
}
.slotBox {
background-color: pink;
width: 200px;
height: 300px;
}
img,
video {
width: 100%;
}
</style>
App组件:
<template>
<div class="container">
<MySlot title="美食">
<img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" />
<a slot="footer" class="foot" href="http://www.baidu.com">更多美食</a>
</MySlot>
<MySlot title="游戏">
<ul slot="center">
<li v-for="(game, index) in games" :key="index">{{ game }}</li>
</ul>
<div slot="footer" class="foot">
<a href="http://www.baidu.com">单机游戏</a>
<a href="http://www.baidu.com">网络游戏</a>
</div>
</MySlot>
<MySlot title="电影">
<video
slot="center"
controls
src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
></video>
<template v-slot:footer>
<div class="foot">
<a href="http://www.baidu.com">经典</a>
<a href="http://www.baidu.com">热门</a>
<a href="http://www.baidu.com">推荐</a>
</div>
<h2>欢迎</h2>
</template>
</MySlot>
</div>
</template>
<script>
import MySlot from "./components/MySlot.vue";
export default {
components: { MySlot },
name: "App",
data() {
return {
foods: ["梨子", "饮料", "其他"],
games: ["冒险岛", "dota2", "魔兽世界"],
movies: ["权利的游戏", "魔法少女小圆", "斩赤红之瞳"],
};
},
};
</script>
<style scoped>
.container,
.foot {
display: flex;
justify-content: space-around;
}
h2 {
text-align: center;
}
</style>
作用域插槽
数据在某组件内,但是想给其父组件定义该组件的结构时候,使用作用域插槽,如本实例中,数据在MySlot中,但是其父组件可以用到MySlot的数据,传的方式类似于父传子的props,但是父组件需要用template将想插入的内容包裹起来,并用scope(最新的为slot-scope)属性接收,该属性不用es6的解构赋值是为一个自定义的变量,并且在v-for的时候需要这个变量.相应的数据,如果是用es6的解构赋值,则可以直接将里面的数据取出来,格式为scope=“{xxx}”。
App组件
<template>
<div class="container">
<MySlot title="美食">
<!-- 这里用的slot-scope,跟scope一样的,并且没用es6,因此自定义了一个接收的变量 -->
<!-- 一定需要用template包裹 -->
<template slot-scope="peiqi">
<ol>
<!-- 接受的为一个对象,因此需要获取里面的数据 -->
<li v-for="(food, index) in peiqi.foods" :key="index">{{ food }}</li>
</ol>
</template>
</MySlot>
<MySlot title="美食">
<!-- 这里用的scope,并且用的es6语法,直接取出对象中的属性 -->
<template scope="{foods}">
<ul>
<!-- 直接用属性即可 -->
<li v-for="(food, index) in foods" :key="index">{{ food }}</li>
</ul>
</template>
</MySlot>
</div>
</template>
<script>
import MySlot from "./components/MySlot.vue";
export default {
components: { MySlot },
name: "App",
};
</script>
<style scoped>
.container,
.foot {
display: flex;
justify-content: space-around;
}
h2 {
text-align: center;
}
</style>
MySlot组件
<template>
<div class="slotBox">
<h1>{{ title }}</h1>
<slot :foods="foods"></slot>
</div>
</template>
<script>
export default {
name: "MyList",
props: ["title"],
data() {
return {
foods: ["梨子", "饮料", "其他"],
};
},
};
</script>
<style scoped>
h1 {
background-color: aqua;
text-align: center;
}
.slotBox {
background-color: pink;
width: 200px;
height: 300px;
}
img,
video {
width: 100%;
}
</style>