vue3 学习笔记10 – 父子组件传参和组件间通信
父子组件之间的传参
父子组件之间的传参可以通过属性(prop)和事件(event)来实现
使用属性(props)传递数据
在子组件中定义 props
- 在子组件中使用 defineProps 来定义接收的属性
// children.vue
<template>
<div>{{ name }}: {{age}}</div><div>{{personal.address}} {{personal.sex}}</div><div v-for="(item,index) in list" :key="index">{{item.phone}}</div>
</template><script lang="ts" setup>
interface Phone {phone: string;
}
interface ChildProps {name: string;age: number;
}
const props = defineProps(['name','age','personal','list'])
// 或者
const props= defineProps({name: {type: String as PropType<string>,default: () => {return ''}},age:{type: Number as PropType<number>,default: () => {return 0} },personal:{type: Object,default: () => {return {}} },list:{type: Array as () => User[],default: () => {return []} }
})
</script>
在父组件中传递参数
- 在父组件中使用子组件的标签,并通过属性传递数据:
// parent.vue<template><childrenTemplate :name="name" :age="age" :personal="personal" :list="list"></childrenTemplate></template><script lang="ts" setup>import childrenTemplate from './components/children.vue'let name = ref('小涨')let age = ref(8)let personal = reactive({address:'上海',sex:'女'})let list = ref([{phone:'1111111'},{phone:'2222222'}])</script>
defineEmits 使用事件进行通信
- 在子组件中定义事件
- 在子组件中,使用 defineEmits 定义事件,并通过 emit 方法触发事件
// children.vue
<template>
<div>{{ name }}: {{age}}</div><div>{{personal.address}} {{personal.sex}}</div><div v-for="(item,index) in list" :key="index">{{item.phone}}</div><el-button @click="handleChangeParent">改变名字</el-button><el-button @click="handleChangeParent2">改变年龄</el-button>
</template><script lang="ts" setup>
interface Phone {phone: string;
}
interface ChildProps {name: string;age: number;
}
const props = defineProps(['name','age','personal','list'])
// 或者
const props= defineProps({name: {type: String as PropType<string>,default: () => {return ''}},age:{type: Number as PropType<number>,default: () => {return 0} },personal:{type: Object,default: () => {return {}} },list:{type: Array as () => User[],default: () => {return []} }
})
const $emit = defineEmits(['childClick','childChangeName']);
const handleChangeParent = ()=>{$emit('childClick',43)
}
const handleChangeParent2 = ()=>{$emit('childChangeName','小明')
}
</script>
- 在父组件中监听事件
- 在父组件中监听子组件触发的事件,并处理数据或者触发相应的方法。
// parent.vue<template><childrenTemplate :name="name" :age="age" :personal="personal" :list="list" @child-click="handleEmit" @child-change-name="handleGet"></childrenTemplate></template><script lang="ts" setup>import childrenTemplate from './components/children.vue'let name = ref('小涨')let age = ref(8)let personal = reactive({address:'上海',sex:'女'})let list = ref([{phone:'1111111'},{phone:'2222222'}])const handleEmit = (val:number)=>{age.value =val}const handleGet = (val:string)=>{name.value = val}</script>
组件间的通信
如果需要在多层级的组件中进行数据传递,可以使用provide 和 inject API。
- 在父组件中提供数据:
<template><div><ChildComponent /></div>
</template><script setup lang="ts">
import { ref, provide } from 'vue';
import ChildComponent from './ChildComponent.vue';let list = ref([{phone:'1111111'},{phone:'2222222'
}])const deleteMsgByIndex = (index)=> {list.value.splice(index, 1);
}
const addMsg = (info)=> {list.value.push(info)
}provide('messageInfo', {list: list,deleteMsgByIndex,addMsg
}); // 提供 counter 数据给子组件
</script>
- 在子组件中注入数据:
<template><button @click="handleAdd">添加</button><div v-for="(item, index) in list" :key='index'><span>{{item.phone}}</span><button @click.prevent="handledelete(index)">删除</button></div></template><script setup lang="ts">
import { inject } from 'vue';const {addMsg,list,deleteMsgByIndex} = inject("messageInfo")
const handleAdd = ()=>{addMsg({phone:'3333333'})
}
const handledelete = (index)=>{deleteMsgByIndex(index)
}
</script>