vuejs3.0 从入门到精通——组件传值方式1——props/$emit(父子传值 )
组件传值方式1 —— props / $emit(父子传值 )
一、父传子
1.1、父组件通过 props 传递数据
在父组件中,创建了一个名为List
的子组件实例,并通过:msg="msg"
语法将父组件的msg
数据传递给子组件。这里的msg
是一个响应式引用(使用ref
创建),初始值为'这是父传过去的数据'
。
<template>
<div>
<List :msg="msg"></List>
</div>
</template>
<script setup lang="ts">
import List from '@/components/List.vue'
import { ref } from 'vue'
let msg = ref('这是父传过去的数据');
</script>
-
:msg="msg"
:这里的冒号(:)是v-bind:
的简写(详细见:https://vuejs.org/api/built-in-directives.html#v-bind),用于动态绑定一个或多个属性,或组件 prop 到表达式的计算值。在这个例子中,它将msg
prop 绑定到msg
的当前值。ref
:是 Vue 3 中的响应式 API 的一部分,用于创建一个响应式的引用。
1.2、子组件
在子组件中,使用了defineProps
函数来定义接收的 props,这里定义了 msg
这个 prop,并指定了它的类型和默认值。
<template>
<div>
这是子组件 ==> {{ msg }}
</div>
</template>
<script setup lang="ts">
defineProps({ //defineProps 是用来定义组件的 props 的一个函数
msg: { //msg 是这个组件接收的一个 prop,它有以下属性
type: String, //表示这个 prop 的类型应该是字符串
default: 'hello', //表示如果没有提供这个 prop, 那么它的默认值会是 'hello'
}
})
</script>
-
- defineProps:是 Vue 3 Composition API 的一部分,用于在 setup 函数中定义组件的 props。它允许你以类型安全的方式定义 props,并提供了对默认值和验证的支持。
- msg:是定义的一个 prop,它的类型是 String,这表示这个 prop 应该接收一个字符串。如果没有传递任何值,那么它的默认值会是 'hello'。
- 在模板中,通过 {{ msg }} 语法,将接收到的 msg prop 显示出来。
二、子传父
在 Vue 3 中,子组件向父组件传递数据的一种常见方式是通过$emit
派发事件。
2.1、子组件中通过$emit
派发事件
在子组件中,你可以使用$emit
方法来触发一个自定义事件。你可以在这个事件中传递任何你想要传递给父组件的数据。
2.1.1、使用$emit
的注意事项
-
- 确保在子组件中触发的事件名与父组件中监听的事件名保持一致。
- 如果在子组件的 setup 方法中使用
$emit
,确保从 setup 函数的参数中获取 emit 函数。 - 在使用
$emit
时,确保事件名和参数是有效的和有意义的,以便于代码的可读性和维护性。
<template>
<div>
// 这里定义了一个子组件的模板。它包含一个显示 num 的文本。
这是子组件 ==> {{ num }}
//这里定义了一个子组件的模板。它包含一个 button 按钮。
//按钮上有一个 @click 监听器,它会在按钮被点击时触发 changeNum 方法。
<button @click='changeNum'>按钮</button>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup(_, { emit }) {
let num = ref(100); // num 是一个响应式引用,初始值为100
const changeNum = () => {
emit('fn', num.value); // 触发一个名为 'fn' 的自定义事件,并传递 num 的当前值
}
return {
num, // 把 num 暴露给模板
changeNum // 把 changeNum 方法暴露给模板
}
}
});
</script>
2.1.2、父组件中监听子组件的事件
在父组件的模板中,可以监听子组件触发的自定义事件。当监听到这个事件时,可以调用父组件中的一个方法来处理这个事件。
<template>
<div>
//@fn 是监听子组件触发的名为 fn 的事件。当这个事件被触发时,它会调用名为 handleFn 的父组件方法
<child-component @fn="handleFn"></child-component>
</div>
</template>
<script lang="ts">
import ChildComponent from '@/components/List.vue'
export default {
components: {
ChildComponent
},
methods: {
//payload 就是子组件通过 $emit 传递的数据
handleFn(payload: number) {
// 打印子组件传递的数据
console.log('Received payload:', payload);
}
}
}
</script>
另外一种实现方式 <script setup lang=‘ts’>
2.2 A组件(Child)
<template> <div> <h1>{{ str }}</h1> <button @click="changeA">按钮</button> </div> </template> <script setup lang='ts'> //从 Vue 库中导入 ref 函数。ref 是 Composition API 的一部分,用于创建响应式引用。 import { ref } from 'vue'; //创建一个响应式引用 str,并初始化为字符串 "这是A组件的数据"。 let str = ref('这是A组件的数据'); /* 使用 defineEmits 函数定义一个名为 fn 的自定义事件。 该组件就可以向外发送名为 fn 的事件,并传递数据。 */ const emit = defineEmits(['fn']); /* 定义一个 changeA 方法。 当该方法被调用时(比如点击按钮),它会使用 emit 发送一个 fn 事件,并传递当前 str 的值。 */ const changeA = () => { emit('fn', str); }; </script>
2.3 父组件
<template> <div> <A @fn="handleFn"></A> <B></B> </div> </template> <script setup lang="ts"> import A from './A.vue' import B from './B.vue' const handleFn = (payload: any) => { console.log('Received payload:', payload); }; </script>