上篇文章 【Vue】Vue3.0(二十四)Vue3.0中 r e f s 、 refs 、 refs、parent 的概念和使用场景
🏡作者主页:点击!
🤖Vue专栏:点击!
⏰️创作时间:2024年11月20日16点30分
文章目录
- 概念
- 使用场景
- 使用示例
- 再来个实例
概念
在Vue 3.0中,具名插槽是插槽的一种特殊形式,它允许父组件向子组件的特定位置插入内容,通过给插槽命名来实现更精确的内容分发。与默认插槽不同,具名插槽可以在一个子组件中定义多个不同名称的插槽,父组件根据这些名称将相应的内容插入到对应的位置,从而使子组件的结构更加灵活和可定制。
使用场景
- 复杂组件的内容定制:当一个组件的内部结构较为复杂,不同部分需要由父组件根据具体业务场景提供不同内容时,具名插槽就非常有用。比如一个包含导航栏、主体内容区和侧边栏的页面布局组件,通过具名插槽,父组件可以分别向这三个区域插入不同的导航链接、具体的页面内容和侧边栏信息,实现页面布局和内容的灵活组合。
- 组件库的开发:在开发组件库时,具名插槽可以让使用者更方便地对组件进行个性化定制。例如,一个通用的卡片组件,可能有标题、内容、操作按钮等不同的区域,通过具名插槽,使用者可以根据自己的需求向这些区域插入不同的文本、图标或按钮等内容,而无需修改组件库的源代码,提高了组件的复用性和灵活性。
使用示例
以下是一个使用具名插槽的示例,包含一个Card
组件和使用该组件的父组件:
Card
组件
<template><div class="card"><div class="card-header"><slot name="header"></slot></div><div class="card-body"><slot name="body"></slot></div><div class="card-footer"><slot name="footer"></slot></div></div>
</template><script setup lang="ts">
import { defineComponent } from 'vue';export default defineComponent({});
</script><style scoped>
.card {border: 1px solid #ccc;border-radius: 5px;overflow: hidden;
}.card-header {background-color: #f0f0f0;padding: 10px;font-weight: bold;
}.card-body {padding: 10px;
}.card-footer {background-color: #f0f0f0;padding: 10px;text-align: right;
}
</style>
在Card
组件中,定义了三个具名插槽:header
、body
和footer
,分别用于显示卡片的头部、主体和底部内容。
- 父组件使用
Card
组件
<template><div><h2>具名插槽示例</h2><Card><template v-slot:header><span>这是卡片的标题</span></template><template v-slot:body><p>这是卡片的主体内容,这里可以填写详细的信息。</p></template><template v-slot:footer><button>查看详情</button></template></Card></div>
</template><script setup lang="ts">
import Card from './Card.vue';
import { defineComponent } from 'vue';export default defineComponent({components: {Card,},
});
</script>
在父组件中,通过<template v-slot:header>
、<template v-slot:body>
和<template v-slot:footer>
分别向Card
组件的对应具名插槽中插入了自定义的内容,如标题、主体内容和操作按钮。这样,就可以根据不同的需求,灵活地定制Card
组件的显示内容,而无需修改Card
组件本身的代码,实现了组件的高度复用和灵活定制。
通过具名插槽,Vue 3.0的组件能够更好地满足各种复杂的页面布局和内容定制需求,提高了代码的可维护性和复用性,使开发者能够更高效地构建应用程序。
再来个实例
最终效果:
代码:
Father.vue
<template><div class="father"><h3>父组件</h3><div class="content"><Category><template v-slot:s2><ul><liv-for="g in games":key="g.id">{{ g.name }}</li></ul></template><template v-slot:s1><h2>热门游戏列表</h2></template></Category><Category><template v-slot:s2><img:src="imgUrl"alt=""></template><template v-slot:s1><h2>今日美食城市</h2></template></Category><Category><!--简写:#s2--><template #s2><videovideo:src="videoUrl"controls></video></template><template #s1><h2>今日影视推荐</h2></template></Category></div></div>
</template><script setup lang="ts" name="Father">
import Category from './Category.vue'
import { ref, reactive } from "vue";let games = reactive([{ id: 'asgytdfats01', name: '英雄联盟' },{ id: 'asgytdfats02', name: '王者农药' },{ id: 'asgytdfats03', name: '红色警戒' },{ id: 'asgytdfats04', name: '斗罗大陆' }
])
let imgUrl = ref('https://z1.ax1x.com/2023/11/19/piNxLo4.jpg')
let videoUrl = ref('http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4')</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%;
}h2 {background-color: orange;text-align: center;font-size: 20px;font-weight: 800;
}
</style>
Category.vue代码
<template><div class="category"><slot name="s1">默认内容1</slot><slot name="s2">默认内容2</slot></div>
</template><script setup lang="ts" name="Category"></script><style scoped>
.category {background-color: skyblue;border-radius: 10px;box-shadow: 0 0 10px;padding: 10px;width: 200px;height: 300px;
}
</style>