简单地来说, defineProps
是父向子传值,defineEmits
是子向父传值
defineProps
父组件:
<template>
<div>
<ChildComponent :message="messageFromParent" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
messageFromParent = ref('Hello Child!')
</script>
子组件:
<template>
<!-- 组件中可以直接用message -->
<p>{{ message }}</p>
</template>
<script setup>
import { ref } from 'vue'
// 可以不用引用
defineProps({
message: {
type: string
}
})
// 在setup中用props.message访问
const message-child = ref('props.message')
</script>
defineEmits
子组件:
<template>
<button @click="sendMsg">发送消息到父组件</button>
</template>
<script setup>
// 先在defineEmits中声明
defineEmits(['childMsg'])
const sendMsg = () => {
const message = 'Hello,父组件!我是子组件'
emit('childMsg', message) // 发送消息到父组件
}
</script>
在上面的例子中,子组件中的sendMsg
方法使用emit('childMsg', message)
方法发送一个自定义事件给父组件,并且传递了一个字符串message
。
父组件:
<template>
<div>
<p>{{ msg }}</p>
<child-component @childMsg="handleChildMsg"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
const msg = ref('')
const handleChildMsg = (msg) => {
console.log(msg) // 打印消息
msg = msg // 更新数据
}
</script>
父组件通过@childMsg
监听子组件发出的事件,并将其绑定到handleChildMsg
方法上。
v-model实现父子组件的双向绑定
首先,v-model
作用在组件上的时候,会被展开成如下形式
<CustomInput
:modelValue="searchText"
@update:modelValue="newValue => searchText = newValue"
/>
接下来我们要做两件事
- 子组件通过
defineProps
添加modelValue
prop - 子组件通过
defineEmits
添加update:modelValue
自定义事件
具体实现如下:
<!-- CustomInput.vue -->
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>
<template>
<input
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
/>
</template>
或者
<!-- CustomInput.vue -->
<script setup>
import { computed } from 'vue'
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
const value = computed({
get() {
return props.modelValue
},
// 其实就是监听子组件的值有没有改变,改变的话向父组件发送事件实现同步
set(value) {
emit('update:modelValue', value)
}
})
</script>
<template>
<input v-model="value" />
</template>