三 defineProps和defineEmits
- defineProps 和 defineEmits 都是只能在 <script setup> 中使用的编译器宏。
- 不需要导入
- defineProps 接收与 props 选项相同的值,defineEmits 接收与 emits 选项相同的值。
- defineProps 和 defineEmits 在选项传入后,会提供恰当的类型推导。
- 传入到 defineProps 和 defineEmits 的选项会从 setup 中提升到模块的作用域
const props = defineProps<{foo: stringbar?: number
}>()const emit = defineEmits<{(e: 'change', id: number): void(e: 'update', value: string): void
}>()
示例:
<!-- MyChildComponent.vue -->
<template><div><p>{{ myProp }}</p><button v-on:click="$emit('myEvent', 'Hello from child!')">Emit event</button></div>
</template><script lang="ts">
import { defineComponent, PropType, EmitType } from 'vue';export default defineComponent({name: 'MyChildComponent',props: {myProp: {type: String as PropType<string>,required: true}},emits: {myEvent: {type: String as EmitType<string>}}
});
</script><!-- MyParentComponent.vue -->
<template><div><MyChildComponent v-bind:myProp="parentProp" v-on:myEvent="handleEvent" /></div>
</template><script lang="ts">
import MyChildComponent from './MyChildComponent.vue';export default {components: {MyChildComponent},data() {return {parentProp: 'Hello from parent!'};},methods: {handleEvent(message: string) {console.log(message);}}
};
</script>
在父组件 MyParentComponent 中使用了子组件 MyChildComponent,
并通过 v-bind 和 v-on 指令进行了传值和事件监听。
在子组件中,我们通过 $emit 方法来触发自定义事件
defineProps 原理
Vue 3 使用了一种叫做 “响应式系统” 的技术来追踪和响应数据变化。当数据发生变化时,Vue 会自动更新视图,以保证数据和视图的一致性。
Vue 使用了一个叫做 “响应式代理” 的技术来实现响应式系统。响应式代理是一个对象,它可以监视对象属性的访问和修改,并在数据发生变化时触发 Vue 的响应机制。
Vue 3 使用了一个叫做 “Reflect” 的内置对象来实现响应式代理。Reflect 对象提供了一系列方法来操作对象的属性和方法,例如获取对象的属性值、设置对象的属性值、删除对象的属性等。
Vue 3 中的 defineProps 方法就是使用 Reflect 对象来实现响应式代理的。它的作用是将对象的属性包装成响应式属性,使得在修改属性时能触发响应式系统。
defineProps 的语法如下:
defineProps(target: object, props: object | Array<string>)
其中 target 是要添加或修改属性的对象,props 是一个对象或字符串数组,包含要添加或修改的属性的名称。
defineEmits 原理
1. defineEmits 是 Vue 3 Composition API 提供的一个方法,它允许你在组件中定义和暴露自定义事件发射器。它类似于 Vue 2 Options API 提供的 emit 方法,但有几个关键的不同之处:
2. defineEmits 是响应式的:发射器的值的变化会自动触发组件的更新。
3. defineEmits 是可组合的:你可以将它与其他 Composition API 函数结合起来,以创建更复杂的行为。
4. defineEmits 是类型安全的:它使用 TypeScript 装饰器语法为你的发射器提供类型检查。
要使用 defineEmits,你需要首先从 vue 模块中导入它:
import { defineEmits } from 'vue';export default defineComponent({emits: ['submit'],methods: {handleSubmit() {this.submit();}}});
在这个例子中,组件定义了一个名为 submit 的发射器,可以通过调用 submit 方法来触发它。
当调用 submit 方法时,它会在组件上触发 submit 事件,父组件或其他任何侦听器都可以侦听这个事件。
思考:setup中的宏编译