Vue.js 父子组件数据传递:props 和事件
今天我们来聊聊 Vue.js 中父子组件之间的数据传递。这是组件化开发的核心之一,理解并掌握它,能让你写出结构清晰的 Vue 应用。
Vue 提供了两个主要的机制来实现父子组件通信:
- props:父组件向子组件传递数据。
- 事件:子组件向父组件发送消息。
让我们一步步来看这两个机制的用法吧!
一、通过 props 传递数据
props 是 Vue 提供的一种机制,用来从父组件向子组件传递数据。子组件通过 props
接收数据,并将它作为只读属性使用。
示例:父组件向子组件传递标题
1. 定义子组件
vue
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script>
export default {
name: 'ChildComponent',
props: {
title: {
type: String,
required: true
}
}
};
</script>
这里子组件定义了一个 props
属性 title
,它接收父组件传递的字符串数据。
2. 使用子组件
vue
<template>
<div>
<ChildComponent title="这是父组件传递的标题" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
name: 'ParentComponent',
components: {
ChildComponent
}
};
</script>
注意事项
- 子组件的
props
是只读的,不能直接修改。 - 可以通过
type
、required
等属性对props
进行类型校验。
二、通过事件发送消息
如果需要从子组件将消息传递给父组件,可以通过自定义事件实现。
示例:子组件发送点击事件
1. 定义子组件
vue
<template>
<button @click="notifyParent">点击我</button>
</template>
<script>
export default {
name: 'ChildComponent',
methods: {
notifyParent() {
this.$emit('button-clicked', '子组件按钮被点击了!');
}
}
};
</script>
这里子组件在按钮点击时,使用 $emit
方法触发了一个自定义事件 button-clicked
,并传递了一个消息。
2. 使用子组件
vue
<template>
<div>
<ChildComponent @button-clicked="handleButtonClick" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
name: 'ParentComponent',
components: {
ChildComponent
},
methods: {
handleButtonClick(message) {
alert(message);
}
}
};
</script>
父组件通过 @button-clicked
监听子组件的事件,并调用 handleButtonClick
方法处理事件。
小结
$emit
用于在子组件中触发自定义事件。- 父组件使用
@事件名
或v-on:事件名
来监听子组件事件。
三、双向绑定的简化写法(v-model
)
在某些场景下,父子组件之间需要实现双向数据绑定,比如表单输入。这时可以用 v-model
提供的简化写法。
示例:子组件支持双向绑定
1. 定义子组件
vue
<template>
<input :value="value" @input="$emit('update:modelValue', $event)" />
</template>
<script>
export default {
name: 'ChildComponent',
props: {
modelValue: String
}
};
</script>
这里通过 v-model
绑定的规范:props
接收 modelValue
,事件触发 update:modelValue
。
2. 使用子组件
vue
<template>
<div>
<ChildComponent v-model="inputValue" />
<p>输入的内容是:{{ inputValue }}</p>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
name: 'ParentComponent',
components: {
ChildComponent
},
data() {
return {
inputValue: ''
};
}
};
</script>
小结
v-model
是父子组件实现双向绑定的快捷方式。- 子组件中需要监听
modelValue
的变化,并通过事件更新值。
四、综合示例:父子双向通信
我们把上面的知识点整合起来,写一个父子双向通信的完整例子。
父组件和子组件的代码
子组件:Counter
vue
<template>
<div>
<button @click="decrement">-</button>
<span>{{ count }}</span>
<button @click="increment">+</button>
</div>
</template>
<script>
export default {
name: 'Counter',
props: {
count: Number
},
methods: {
increment() {
this.$emit('update:count', this.count + 1);
},
decrement() {
this.$emit('update:count', this.count - 1);
}
}
};
</script>
父组件:App
vue
<template>
<div>
<Counter v-model:count="totalCount" />
<p>当前计数:{{ totalCount }}</p>
</div>
</template>
<script>
import Counter from './Counter.vue';
export default {
name: 'App',
components: {
Counter
},
data() {
return {
totalCount: 0
};
}
};
</script>
效果
- 父组件通过
v-model
绑定计数值。 - 子组件负责增减计数,并通知父组件更新值。
五、总结
父子组件通信是 Vue 的基础功能,主要依靠两种机制:
- props:从父组件向子组件传递数据(单向数据流)。
- 事件 :子组件通过
$emit
通知父组件,支持双向通信。
此外,v-model
是简化父子组件双向绑定的快捷方式。