一、父传子
基本语法:
- 定义子组件:在子组件中,使用
defineProps
来声明接收的 props。可以使用数组或对象的方式来定义 props。 - 在父组件中使用子组件并传递数据:在父组件中引用子组件,并通过 props 将数据传递给子组件。
defineProps 函数的介绍:
defineProps
是一个用于定义组件接收的 props 的函数。调用 defineProps
后,它会返回一个包含所有定义的 props 的响应式对象。
示例1:对于数组的方式定义
// 儿子.vue
<template>
<div>这是儿子里面的:</div>
{{ props.name }}{{ props.age }}
</template>
<script setup>
import { defineProps } from 'vue';
// 1. 使用数组来定义
const props = defineProps(['name', 'age']);
// 定一个方法接收
const a = () => {
console.log(props.name,props.age);
}
</script>
// 父亲.vue
<template>
这个父亲里面的:<child name="刘肉面" :age="age"></child>
</template>
<script setup>
import { ref } from 'vue';
import Child from './儿子.vue';
const age = ref(22)
</script>
说明:
1.子组件:(儿子.vue)中
import { defineProps } from 'vue';
: 从 Vue 中导入defineProps
函数,用于定义组件的 props。const props = defineProps(['name', 'age'])
: 使用defineProps
定义当前组件的 props,接收父组件传递的name
和age
属性(或者理解为:子组件需要这两个参数的数据,那么就需要父组件传递过来)。这里使用了数组的形式来定义 props。const a = () => { console.log(props.name, props.age); }
: 定义一个方法a
,它会将name
和age
的值打印到控制台。这个方法可以在需要的时候调用。
2.父组件:(父亲.vue)中
<child name="lhl" :age="age"></child>
: 这里使用了一个名为Child
的子组件(从儿子.vue
文件导入)。我们给子组件传递了两个属性:name 和 age (这两个属性名和子组件中接受的命名一致)import { ref } from 'vue';
: 从 Vue 中导入ref
函数,用于创建响应式数据。import Child from './儿子.vue';
: 导入子组件Child
(即儿子.vue
)。const age = ref(22);
: 创建一个响应式变量age
,初始值为22
。这个变量可以在模板中使用,并且如果它的值发生变化,Vue 会自动更新任何引用到这个变量的地方。
注意事项:
- 父组件传递的 prop 名称(如
usrname
和age
)必须与子组件中定义的 prop 名称一致。 - 如果父组件传递的 prop 名称与子组件定义的名称不一致,子组件将无法接收到相应的值。
示例2:对于对象的方式定义
-
type属性:定义属性的数据类型。可以是内置的 JavaScript 构造函数(如 String、Number、Boolean、Object、Array)或自定义构造函数。
-
default属性:指定属性的默认值。如果在使用组件时未提供该属性,将使用默认值
-
validator:自定义验证函数,用于验证属性的有效性。该函数应返回
true
或false。
-
required:声明属性是否是必须的。如果设置为
true
,在组件使用时必须传递该属性。
// 儿子.vue
<template>
<div>这是儿子里面的:</div>
{{ props.name }}{{ props.age }}
</template>
<script setup>
import { defineProps } from 'vue';
// 1. 使用对象来定义
// name 必传 String 类型的数据
// age 不必传 number数据类型 默认值为20
const props = defineProps({
name: {
required: true,
type: String,
},
age: {
required: false, // 默认 false
type: Number,
default: 20,
}
})
// 定一个方法接收
const a = () => {
console.log(props.name,props.age);
}
</script>
// 父亲.vue
<template>
这个父亲里面的:<child name="刘肉面" :age="18"></child>
</template>
<script setup>
import { ref } from 'vue';
import Child from './儿子.vue';
// const age = ref(22)
</script>
说明:
子组件中:(儿子.vue)中
-
const props = defineProps({...});
:使用对象形式来定义组件的 props。name: { required: true, type: String }
:name
是一个必传的属性,类型为String
。
age: { required: false, type: Number, default: 20 }
:age
是一个可选的属性,类型为Number
,如果父组件没有传递这个属性,则默认值为20
。
父组件中:(父亲.vue)中
- 父组件通过
<child>
标签向 子组件传递了name
和age
两个 prop。name
是固定的字符串,而age
是数字。(通过 动态绑定 改变数据类型)
defineProps 函数的使用:
1.返回的对象:
const props = defineProps(['customName', 'customAge']);
这行代码定义了两个 props,分别是customName
和customAge
。props
变量将会是一个响应式对象,包含这两个 props 的值。
2.使用 props:
- 在组件的模板中,可以直接使用
props.customName
和props.customAge
来访问这些 props 的值。 - 这些值会自动响应父组件传递给子组件的 props 更新。
注意事项:
-
数据流向: 数据在 Vue 中是单向流动的,即从父组件流向子组件。这意味着子组件不能直接修改 props 的值。
-
响应式: 如果父组件中的数据是响应式的(使用
ref
或reactive
创建),子组件会自动接收到更新后的值。 -
类型和默认值: 在子组件中可以使用对象形式的
defineProps
来指定 props 的类型和默认值。
二、子传父
- 子组件通过自定义事件的方式来向父组件传递数据
- 子组件通过defineEmits方法,定义可以向父组件传递的事件
- defineEmits是一个方法,他能接受数组,数组之中每一个字符串,都代表一个可以向父组件emit 的事件
- 特殊的子传父:父组件通过 props ,传递一个方法给子组件,子组件通过调用此方法,来更新数据到父组件。
defineEmits 介绍:
defineEmits
是一个用于定义组件可以发出的事件的函数。调用 defineEmits
后,它会返回一个 emit
函数,这个函数可以用来触发定义的事件。
示例1:对于数组的方式定义
// 儿子.vue
<template>
儿子里面的:
<button @click="toFather">点击传给父亲</button>
</template>
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['success']);
function toFather() {
emit("success", "这里写需要传递给父亲的数据");
}
</script>
<style>
</style>
// 父亲.vue
<template>
<Child @success="getMessage"></Child>
</template>
<script setup>
import { ref } from 'vue';
import Child from './儿子.vue';
const getMessage = (value) => {
console.log(value);
}
</script>
<style>
</style>
说明:
子组件中:
-
const emit = defineEmits(['success'])
:定义了一个名为success
的事件。这个事件可以在子组件中被触发,并可以向父组件传递数据。 -
function toFather() {...}
:这个函数在按钮点击时被调用。在这里,我们使用emit
方法触发success
事件,并传递了一个字符串"这里写需要传递给父亲的数据"
。
父组件中:
-
const getMessage = (value) => {...}
:这个函数定义了如何处理从子组件传递过来的数据。当success
事件被触发时,这个函数会被调用,并接收子组件传递的数据作为参数value
。这里的实现是将数据打印到控制台。
事件工作流程:
- 用户交互:用户在子组件中点击按钮。
- 事件触发:
toFather
方法被调用,子组件通过emit
方法触发success
事件,并传递数据。 - 父组件响应:父组件监听到
success
事件,调用getMessage
方法,并将子组件传递的数据作为参数传入。 - 数据处理:
getMessage
方法执行,将接收到的数据打印到控制台。
defineEmits 函数使用说明:
const emit = defineEmits(['success']);
这行代码定义了一个名为success
的事件,并将emit
函数赋值给变量emit
。emit
函数可以用来触发这个事件,并可以传递数据给监听该事件的父组件。- 一旦定义了事件,就可以通过调用 emit 函数来出发这个事件:
- emit('success', '这里是要传递的数据'):这个代码会触发
success
事件,并将'这里是要传递的数据'
作为参数传递给监听该事件的父组件。(给到父组件里面的 getMessage 中的 value)。 emit
函数的第一个参数是事件的名称,后面的参数是要传递给父组件的数据。- 可以传递任意数量的参数,父组件在处理事件时会接收到这些参数。
示例2:对应对象的方式定义
// 儿子.vue
<template>
儿子里面的:
<button @click="toFather">点击传给父亲</button>
</template>
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['success']);
function toFather() {
emit("success", {message: '这个对象方式传递的数据', data: 20});
}
</script>
<style>
</style>
// 父亲.vue
<template>
<Child @success="getMessage"></Child>
</template>
<script setup>
import { ref } from 'vue';
import Child from './儿子.vue';
const getMessage = (obj) => {
console.log('接收到子组件传递的信息:',obj.message);
console.log('接收到子组件传递的信息:',obj.data);
}
</script>
<style>
</style>
- 数组方式:子组件通过
emit
函数传递多个参数,父组件在处理事件时可以接收这些参数。 - 对象方式:子组件通过
emit
函数传递一个对象,父组件在处理事件时可以通过对象的属性访问数据。