前言:如何实现组件的灵活使用,今天学习组件封装用到的props、slot和emit。
目录
props
子组件
父组件
示例代码
slot
示例代码
作用域插槽
emit
示例代码
props
需要实现在其他组件中使用同一个子组件。
子组件
子组件(所谓子组件,就是封装好的组件,供其他组件使用)
子组件定义了sonName
<div>我是MRJJ_9{{sonName}}</div>
defineProps(['sonName'])
或 const props=defineProps(['sonName'])
props是只读的,尽量不要去修改
定义多个
const props=defineProps(['sonName1','sonName2'])
但通常使用数组定义
const props = defineProps({
sonName1: Object,
sonName: Number,})
父组件
父组件(所谓父组件,就是引用封装好的其他子组件)
<Mrjj-Counter :sonName="sonName"></Mrjj-Counter>
let sonName=ref("引用子组件")
示例代码
子组件设置
<template>
<div>我是MRJJ_9的第一个属性,类型为字符串,内容是:{{ sonName1 }},第二个属性,类型是数字,数值为:{{ sonName2 }}</div>
</template>
<script setup>
const props = defineProps({
sonName1: String,
sonName2: Number,
})
console.log("属性1",props.sonName1)
console.log("属性2",props.sonName2)
</script>
<style lang="scss" scoped>
</style>
父组件设置
<template>
<mrjj-son :sonName1="sonName1" :sonName2="sonName2"></mrjj-son>
</template>
<script setup>
import MrjjSon from '@/components/MrjjSon.vue'
import { ref } from 'vue'
let sonName1 = ref('hello,world!!!')
let sonName2 = ref(999)
</script>
<style lang="scss" scoped>
</style>
要注意不能去修改里面的值
slot
需要实现在其他组件中使用同一个组件(子组件),但组件样式的有所区别
这就需要用到插槽:slot,其作用是传参时可以带上HTML结构
子组件带上slot
{{ sonName }}<slot></slot>
父组件将需要传递的内容写到子组件标签里
<mrjj-son><strong>{{sonName }}</strong></mrjj-son>
具名插槽,给插槽命名
有多个值时
子组件加上name
父组件,用v-slot:插槽名(或#插槽名)
示例代码
子组件设置
<template>
<div>
{{ sonName1 }}
<slot name="mrjj1"></slot>
{{ sonName2 }}
<slot name="mrjj2"></slot>
</div>
</template>
<script setup>
const props = defineProps({
sonName1: String,
sonName2: Number
})
</script>
<style lang="scss" scoped>
</style>
父组件设置
<template>
<mrjj-son>
<template #mrjj1
><strong>{{ sonName1 }}</strong></template
>
<template #mrjj2
><i>{{ sonName2 }}</i></template
>
</mrjj-son>
</template>
<script setup>
import MrjjSon from '@/components/MrjjSon.vue'
import { ref } from 'vue'
let sonName1 = ref('hello,world!!!')
let sonName2 = ref(999)
</script>
<style lang="scss" scoped>
</style>
效果展示
作用域插槽
子组件
<template>
<div>
{{ sonName3 }}
<slot name="mrjj3" :times="count" :mrjj1="name"></slot>
</div>
</template>
<script setup>
import { ref } from 'vue'
const props = defineProps({
sonName3: String
})
let count = ref(0)
let name = ref('计数器')
</script>
<style lang="scss" scoped>
</style>
父组件
<template #mrjj3="{ times }"
<template>
<mrjj-son>
<template #mrjj3="{ times }"
><i>{{ sonName3 }}</i>
<Times :times="times"></Times>
</template>
</mrjj-son>
</template>
<script setup>
import MrjjSon from '@/components/MrjjSon.vue'
import Times from '@/components/Times.vue'
import { ref } from 'vue'
let sonName3 = ref('')
</script>
<style lang="scss" scoped>
</style>
引用的Time.vue文件
<template>
<h1>显示Mrjj{{ times }}</h1>
</template>
<script setup>
defineProps(['times'])
</script>
emit
需求:增加一个关闭、打开的组件功能
用到emit,emit干了什么事情呢?在子组件中触发一个事件,在父组件中进行监听。
示例代码
子组件定义一个自定义事件
<template>
<div>
{{ sonName1 }}
<slot name="mrjj1"></slot>
{{ sonName2 }}
<slot name="mrjj2"></slot>
<button @click="closeSon">点我关闭</button>
</div>
</template>
<script setup>
const props = defineProps({
sonName1: String,
sonName2: Number
})
const emit = defineEmits(['closeMrjj'])
function closeSon() {
console.log('关闭按钮被点击了!')
emit('closeMrjj')
}
</script>
<style lang="scss" scoped>
</style>
父组件绑定事件
<template>
<mrjj-son @closeMrjj="closeMrjj" v-if="isClose">
<template #mrjj1
><strong>{{ sonName1 }}</strong></template
>
<template #mrjj2
><i>{{ sonName2 }}</i></template
>
</mrjj-son>
<button v-else @click="($event) => (isClose = true)">点我打开</button>
</template>
<script setup>
import MrjjSon from '@/components/MrjjSon.vue'
import { ref } from 'vue'
let sonName1 = ref('hello,world!!!')
let sonName2 = ref(999)
let isClose = ref(false)
function closeMrjj() {
isClose.value = false
}
</script>
<style lang="scss" scoped>
</style>
效果展示
点我关闭按钮,点击后,调用了closeSon函数,可以看到console输出的信息。
点击展开后,也可以展示出内容。