插槽
在开发中,我们会经常封装一个个可复用的组件,前面我们会通过props传递给组件一些数据,让组件来进行展示,但是为了让这个组件具备更强的通用性,我们不能将组件中的内容限制为固定的div、span等等这些元素,比如某种情况下我们希望组件显示的是一个按钮又或者某种情况下我们使用组件希望显示的是一张图片,因此我们应该让使用者去决定某一块区域到底存放什么内容。
1,插槽的基本使用
(1)我们某个组件中有一个插槽,我们可以在插槽中放入需要显示的内容;
<template>
<div>
<slot></slot>
</div>
</template>
(2)我们在某个组件中使用它,我们可以插入普通的内容、html元素、组件元素都是可以的;
<template>
<div>
<my-slot-cpn>
<!-- 1,插入普通的内容 -->
我是普通的文本
<!-- 2,插入html元素 -->
<button>我是按钮</button>
<!-- 3,插入组件 -->
<my-button/>
</my-slot-cpn>
</div>
</template>
有时候我们希望在使用插槽时,如果没有插入对应的内容,那么我们需要显示一个默认的内容,当然这个默认的内容只会在没有提供插入的内容时,才会显示。
<template>
<div>
<slot>
<i>我是默认的i元素</i>
</slot>
</div>
</template>
2,具名插槽的使用
//父组件
<template>
<div>
<nav-bar :name="name">
<!-- #为v-slot:的语法糖 -->
<template #left>
<button>左边的按钮</button>
</template>
<template #center>
<h2>我是标题</h2>
</template>
<template #right>
<i>右边的i元素</i>
</template>
<!-- 允许父组件自定义插槽的名称 -->
<template #[name]>
<i>why内容</i>
</template>
</nav-bar>
</div>
</template>
<script>
import NavBar from './NavBar.vue';
export default {
components: {
NavBar
},
data() {
return {
name: "why"
}
}
}
</script>
子组件:
注意:接收父组件传递过来的自定义name。
<template>
<div class="nav-bar">
<div class="left">
<slot name="left"></slot>
</div>
<div class="center">
<slot name="center"></slot>
</div>
<div class="right">
<slot name="right"></slot>
</div
<div class="addition">
<!-- 获取并使用父组件传递过来的name -->
<slot :name="name"></slot>
</div>
</div>
</template>
<script>
export default {
props: {
name: String
}
}
</script>
具名插槽简单来说就是提前布局好基础布局,然后在使用时根据具体的插槽名进行使用,当然也允许自定义插槽的名称。
3,作用域插槽的使用
首先得需要了解渲染作用域的概念:父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是在子级作用域中进行编译的,意思也就是你父组件无法访问到子组件的数据的,但是有时候我们确实希望父组件在使用插槽的同时也可以访问到子组件中的内容,因此vue便给我们提供了作用域插槽。
//父组件
<template>
<div>
<show-names :names="names">
//这里的这个coderwhy名称可以自己随便定义
<template v-slot="coderwhy">
<button>{{coderwhy.item}}-{{coderwhy.index}}</button>
</template>
<template v-slot:why>
<h2>我是why的插入内容</h2>
</template>
</show-names>
<show-names :names="names">
<template v-slot="slotProps">
<strong>{{slotProps.item}}-{{slotProps.index}}</strong>
</template>
</show-names>
</div>
</template>
<script>
import ShowNames from './ShowNames.vue';
export default {
components: {
ShowNames
},
data() {
return {
names: ["why", "kobe", "james", "curry"]
}
}
}
</script>
//子组件
<template>
<div>
<template v-for="(item, index) in names" :key="item">
<slot :item="item" :index="index"></slot>
</template>
</div>
</template>
<script>
export default {
props: {
names: {
type: Array,
default: () => []
}
}
}
</script
以上整体的思路就是:先将数据通过父传子的形式传递给子组件,子组件定义为插槽的形式去在父组件中使用,那么此时便可以在父组件中使用子组件中的数据了。