前端工程中多次使用父子组件,对于父子组件之间的传值整理一下,不过常用的方式就两种,详细的讲解一下
1. 父组件向子组件传值(props
)
父组件通过 props
向子组件传递数据,子组件通过 props
接收父组件的数据。
适用于父组件传值给子组件展示,子组件不修改该值,如果子组件双向绑定传过来的值,会有问题,下面父子组件双向传值会讲。
示例代码 父组件 Parent.vue
<template>
<div>
<h2>父组件</h2>
<my-child :childMessage="parentMessage" :childCount="parentCount" />
</div>
</template>
<script>
import MyChild from './MyChild.vue';
export default {
components: { MyChild }, //在父组件中引入子组件元素
data() {
return {
parentMessage: 'Hello from Parent!',
parentCount: 42
};
}
};
</script>
子组件 MyChild.vue
<template>
<div>
<h3>子组件</h3>
<p>父组件传递的消息:{{ childMessage }}</p>
<p>父组件传递的数字:{{ childCount }}</p>
</div>
</template>
<script>
export default {
props: {
childMessage: String, // 类型校验
childCount: Number
}
};
</script>
2. 子组件向父组件传值($emit
)
子组件通过 $emit
触发父组件的事件
父组件监听子组件的事件并处理数据。
示例代码 子组件 MyChild.vue
<template>
<div>
<h3>子组件</h3>
<button @click="sendMessageToParent">点击传递数据给父组件</button>
</div>
</template>
<script>
export default {
methods: {
sendMessageToParent() {
this.$emit('child-event', 'Hello from Child!');
}
}
};
</script>
父组件 Parent.vue
<template>
<div>
<h2>父组件</h2>
<my-child @child-event="handleChildEvent" />
<p>子组件传递的消息:{{ childMessage }}</p>
</div>
</template>
<script>
import MyChild from './MyChild.vue';
export default {
components: { MyChild },
data() {
return {
childMessage: ''
};
},
methods: {
handleChildEvent(message) {
this.childMessage = message;
}
}
};
</script>
3. 双向绑定(v-model
或 .sync
)
如果需要父子组件双向同步数据,可以使用 v-model
或 .sync
(Vue 2.x)。
子组件 MyChild.vue
<template>
<div>
<input
:value="childValue"
@input="$emit('update:childValue', $event.target.value)"
>
</div>
</template>
<script>
export default {
props: ['childValue']
};
</script>
父组件 Parent.vue
v-bind:childValue="parentValue",v-on:update:childValue="val => parentValue = val"简化为
:childValue="parentValue" @update:childValue="val => parentValue = val"进一步简化为
:childValue.sync="parentValue"
<template>
<my-child :childValue.sync="parentValue" />
</template>
<script>
import MyChild from './MyChild.vue';
export default {
components: { MyChild },
data() {
return {
parentValue: ''
};
}
};
</script>
注意:props 是只读的,所以子组件中无法直接用v-model双向绑定父组件传过来的值,子组件修改input输入之后,通知父组件更新,父组件更新后,子组件childValue再更新,绕了一圈
但是我现在就是想在子组件中用v-model进行双向绑定,此时需要修改如下:
子组件 MyChild.vue
<template>
<div>
<input
v-model="childValueCopy" @input="childValueCopyChange"
>
</div>
</template>
<script>
export default {
props: ['childValue'] //父组件传过来的值
data(){
return{
childValueCopy:''
}
}
//此处增加一个监听,监听父组件传过来的值是否变化,如果变化,则赋值给子组件childValueCopy
watch: {
childValue: {
deep: true,
immediate: true,
handler(newValue) {
this.childValueCopy = newValue;
}
}
}
//需要增加一个方法,子组件如果变化了,通知父组件更新
methods:{
childValueCopyChange(value){
this.$emit('update:childValue',value);
//此处注意,需要用value,不能用this.childValueCopy,
//因为@change方法调用比双向绑定v-model更快,
//执行change方法时,childValueCopy还没有变化
}
}
};
</script>
或者
<template>
<input v-model="localValue" />
</template>
<script>
export default {
props: ['value'],
data() {
return {
localValue: this.value // 初始化副本
}
},
watch: {
localValue(newVal) {
this.$emit('input', newVal) // 通知父组件
},
value(newVal) {
this.localValue = newVal // 同步父组件更新
}
}
}
</script>
4. $refs获取子组件的值
子组件中$emit是父组件被动更新,这样子组件每次键入一个字母就会通知父组件一次,会频繁的通知父组件。
父组件可以采用$refs主动获取子组件的值,父组件如下
<template>
<my-child :childValue.sync="parentValue" ref="childComponentRef"/>
</template>
<script>
import MyChild from './MyChild.vue';
export default {
components: { MyChild },
data() {
return {
parentValue: ''
};
},
methods:{
getChildValue(){
console.info("获取子组件值",this.$refs.childComponentRef.childValueCopy)
}
}
};
</script>
扩展知识:
methods: {
childValueCopyChange(value) {
this.$emit('update:childValue', value);
}
}
与methods: {
childValueCopyChange() {
this.$emit('update:childValue', this.childValueCopy);
}
}区别
代码版本 | 数据来源 | 实时性 | 优点 |
---|---|---|---|
第一个代码 | 直接从 立即将最新输入值通过事件对象发出 |
更实时准确 |
|
第二个代码 | 组件内部数据 | 可能有微小延迟 |
|