上篇文章 【Vue】Vue3.0(二十五)Vue3.0中的具名插槽 的概念和使用场景
🏡作者主页:点击!
🤖Vue专栏:点击!
⏰️创作时间:2024年11月20日17点30分
文章目录
- 概念
- 使用场景
- 示例
- 再来个例子
概念
在Vue 3.0中,作用域插槽是一种特殊的插槽,它允许子组件向父组件传递数据,使得父组件在使用插槽时能够访问和使用子组件中的数据。通过作用域插槽,父组件可以根据子组件提供的数据来动态地渲染插槽内容,从而实现更灵活的组件组合和数据传递。
使用场景
- 数据驱动的组件渲染:当子组件内部有一些数据,需要根据这些数据在父组件中进行不同的展示或处理时,作用域插槽就非常有用。例如,一个列表组件,子组件负责获取和管理列表数据,而父组件则根据列表项的不同属性来决定如何展示每个列表项,这时就可以使用作用域插槽将列表项数据传递给父组件进行定制化渲染。
- 组件的灵活扩展:在开发可复用组件时,作用域插槽可以让组件的使用者根据自己的业务需求对组件进行灵活扩展。比如一个通用的表格组件,子组件提供表格的数据和基本结构,父组件通过作用域插槽可以根据不同的列数据进行特殊的格式化或添加额外的操作按钮等,而无需修改表格组件的内部逻辑,提高了组件的复用性和可扩展性。
示例
以下是一个使用作用域插槽的示例,包含一个List
组件和使用该组件的父组件:
List
组件
<template>
<div class="list">
<ul>
<li v-for="item in items" :key="item.id">
<slot :item="item">{{ item.name }}</slot>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { defineComponent, reactive } from 'vue';
const items = reactive([
{ id: 1, name: '苹果', price: 5 },
{ id: 2, name: '香蕉', price: 3 },
{ id: 3, name: '橙子', price: 4 },
]);
export default defineComponent({
setup() {
return {
items,
};
},
});
</script>
<style scoped>
.list {
background-color: lightgray;
padding: 10px;
border-radius: 5px;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin-bottom: 5px;
padding: 5px;
border-radius: 3px;
background-color: white;
}
</style>
在List
组件中,通过:item="item"
将列表项item
对象作为属性传递给了插槽,这就定义了一个作用域插槽。子组件内部有一个items
数组,包含了一些水果的信息,每个列表项都有id
、name
和price
属性。
- 父组件使用
List
组件
<template>
<div>
<h2>作用域插槽示例</h2>
<List>
<template v-slot="{ item }">
<span>{{ item.name }}</span> - <span>价格: {{ item.price }}</span>
</template>
</List>
</div>
</template>
<script setup lang="ts">
import List from './List.vue';
import { defineComponent } from 'vue';
export default defineComponent({
components: {
List,
},
});
</script>
在父组件中,使用<template v-slot="{ item }">
接收了子组件传递过来的item
对象,然后根据item
对象的name
和price
属性来定制化地渲染每个列表项的内容。这样,父组件就可以根据子组件提供的数据进行灵活的展示,而无需修改子组件的内部逻辑。
通过这个例子可以看出,作用域插槽使得子组件和父组件之间的数据传递和交互更加灵活,能够满足各种复杂的业务需求,提高了组件的复用性和可维护性。
再来个例子
效果:
代码:
Father.vue:
<template>
<div class="father">
<h3>父组件</h3>
<div class="content">
<Game>
<template v-slot="params">
<ul>
<li v-for="y in params.youxi" :key="y.id">{{y.name}}</li>
</ul>
</template>
</Game>
<Game>
<template v-slot="params" >
<ol>
<li v-for="item in params.youxi" :key="item.id">{{item.name}}</li>
</ol>
</template>
</Game>
<Game>
<template v-slot="{youxi}">
<h3 v-for="item in youxi" :key="item.id">{{item.name}}</h3>
</template>
</Game>
</div>
</div>
</template>
<script setup lang="ts" name="Father">
import Game from './Game.vue'
</script>
<style scoped>
.father {
background-color: rgb(165, 164, 164);
padding: 20px;
border-radius: 10px;
}
.content {
display: flex;
justify-content: space-evenly;
}
img,
video {
width: 100%;
}
</style>
Game.vue:
<template>
<div class="game">
<h2>游戏列表</h2>
<slot :youxi =games x="哈哈" y="你好"></slot>
</div>
</template>
<script setup lang="ts" name="Game">
import { reactive } from 'vue'
let games = reactive([
{ id: 'asgytdfats01', name: '英雄联盟' },
{ id: 'asgytdfats02', name: '王者农药' },
{ id: 'asgytdfats03', name: '红色警戒' },
{ id: 'asgytdfats04', name: '斗罗大陆' }
])
</script>
<style scoped>
.game {
width: 200px;
height: 300px;
background-color: skyblue;
border-radius: 10px;
box-shadow: 0 0 10px;
}
h2 {
background-color: orange;
text-align: center;
font-size: 20px;
font-weight: 800;
}
</style>