组件通信-<slot>
目录
1. 默认插槽
2. 具名插槽
3. 作用域插槽
1. 默认插槽
父组件:
<template><div class="father"><h3>父组件</h3><div class="container"><Category title="今日游戏推荐"><ul><li v-for="item in games" :key='item.id'>{{ item.name }}</li></ul></Category><Category title="今日美食城市"><img :src="imageUrl" alt="" /></Category><Category title="今日影视推荐"><video :src="videoUrl" controls></video></Category></div></div>
</template><script setup lang="ts" name="Father">
import Category from './Category.vue'
import { ref, reactive } from 'vue'
let games = reactive([{ id: 'asgdytsa01', name: '英雄联盟' },{ id: 'asgdytsa02', name: '王者荣耀' },{ id: 'asgdytsa03', name: '红色警戒' },{ id: 'asgdytsa04', name: '斗罗大陆' }
])
let imageUrl = ref('https://img-blog.csdnimg.cn/direct/fb1e1f109889467a85eec6af0984611c.png')
let videoUrl = ref('https://media.w3.org/2010/05/sintel/trailer.mp4')
</script>
<style scoped>
.father {background-color: pink;padding: 20px;
}.container {display: flex;justify-content: space-evenly;
}img,
video {width: 100%;
}
</style>
子组件:
<template><div class="category"><h2>{{ title }}</h2><slot>默认内容</slot></div>
</template><script setup lang="ts" name="Category">
defineProps(['title'])
</script>
<style scoped>
.category {width: 200px;height: 300px;background-color: aquamarine;
}h2 {background-color: chartreuse;width: 100;text-align: center;
}
</style>
2. 具名插槽
<template><div class="father"><h3>父组件</h3><div class="container"><Category><template v-slot:s2><ul><li v-for="item in games" :key='item.id'>{{ item.name }}</li></ul></template><template v-slot:s1><h2>今日游戏推荐</h2></template></Category><Category><template v-slot:s2><img :src="imageUrl" alt="" /></template><template v-slot:s1><h2>今日图片推荐</h2></template></Category><Category><!-- 写法 v-slot:s2 也可以 #s2 --><template #s2><video :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: 'asgdytsa01', name: '英雄联盟' },{ id: 'asgdytsa02', name: '王者荣耀' },{ id: 'asgdytsa03', name: '红色警戒' },{ id: 'asgdytsa04', name: '斗罗大陆' }
])
let imageUrl = ref('https://img-blog.csdnimg.cn/direct/fb1e1f109889467a85eec6af0984611c.png')
let videoUrl = ref('https://media.w3.org/2010/05/sintel/trailer.mp4')
</script>
<style scoped>
.father {background-color: pink;padding: 20px;
}.container {display: flex;justify-content: space-evenly;
}img,
video {width: 100%;
}h2 {background-color: chartreuse;width: 100;text-align: center;
}
</style>
子组件:
<template><div class="category"><h2>{{ title }}</h2><slot name="s1">默认内容</slot><slot name="s2">默认内容</slot></div>
</template><script setup lang="ts" name="Category">
defineProps(['title'])
</script>
<style scoped>
.category {width: 200px;height: 300px;background-color: aquamarine;
}</style>
3. 作用域插槽
-
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(新闻数据在
News
组件中,但使用数据所遍历出来的结构由App
组件决定) -
具体编码:
父组件:
<template><div class="father"><h3>父组件</h3><div class="container"><!-- <Game v-slot:default="params"> --><!-- <Game #default="params"> --><Game v-slot="params"><ul><li v-for="g in params.games" :key="g.id">{{ g.name }}</li></ul></Game></div></div>
</template><script setup lang="ts" name="Father">
import Game from './Game.vue'</script>
<style scoped>
.father {background-color: pink;padding: 20px;
}.container {display: flex;justify-content: space-evenly;
}img,
video {width: 100%;
}h2 {background-color: chartreuse;width: 100;text-align: center;
}
</style>
子组件:
<template><div class="category"><h2>今日游戏榜单</h2><slot :games="games" a="哈哈"></slot></div>
</template><script setup lang="ts" name="Category">
import { reactive } from 'vue'
let games = reactive([{ id: 'asgdytsa01', name: '英雄联盟' },{ id: 'asgdytsa02', name: '王者荣耀' },{ id: 'asgdytsa03', name: '红色警戒' },{ id: 'asgdytsa04', name: '斗罗大陆' }
])
</script>
<style scoped>
.category {width: 200px;height: 300px;background-color: aquamarine;
}
</style>