Vue子孙三代的三级组件通信
1、首先是一个简单的示例
三个文件
app.vue # 自定义的业务,调用自己封装的组件child.vue
child.vue # 自己封装的第三方组件plug.vue,便于上层调用
plug.vue # 第三方组件,提供v-model数据绑定
- 1
- 2
- 3
调用层次结构
app -> child -> plug
- 1
child在这里起到一个承上启下的桥梁功能
代码
app.vue
<template> <div> <p >app.vue 父组件:{{value}}</p> <button @click="changeValue">父组件+1</button> <child v-model="value"/> </div>
</template>
<script>
import child from './Child.vue';
export default { components:{ child }, data(){ return { value: 0 } }, methods:{ changeValue(){ this.value++; } }
}
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
Child.vue
<template>
<div> <p>child.vue 子组件:{{value}}</p> <button @click="changeValue">子组件+1</button> <plug v-model="value" @input="$emit('input', $event)"/>
</div>
</template>
<script>
import plug from "./Plug.vue";
export default {
props: ["value"], components: { plug
}, methods: { changeValue() { this.value++; this.$emit('input', this.value) }
}
};
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
Plug.vue
<template>
<div> <p>plug.vue 插件:{{value}}</p> <input type="text" :value="value" @input="$emit('input', $event.target.value)" />
</div>
</template>
<script>
export default {
props: ["value"]
};
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
修改app值
这样做可以实现 app<->child<->plug 之间数据同步,不过会有一个警告
[Vue warn]:
Avoid mutating a prop directly since the value will be overwritten
whenever the parent component re-renders.
Instead, use a data or computed property based on the prop's value.
Prop being mutated: "value"
- 1
- 2
- 3
- 4
- 5
原因是vue2中的数据只能单向流动,不能修改外层数据
child 组件中修改了value值
解决方案
修改child.vue 的value为data属性, 警告消失
<template>
<div> <p>child.vue 子组件:{{value}}</p> <button @click="changeValue">子组件+1</button> <plug v-model="innerVlaue" @input="$emit('input', $event)"/>
</div>
</template>
<script>
import plug from "./Plug.vue";
export default {
props: ["value"], components: { plug
}, // 添加data属性
data(){ return { innerVlaue: this.value }
}, methods: { changeValue() { this.innerVlaue++; this.$emit('input', this.innerVlaue) }
}
};
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
遇到如下问题
1、修改app的值,可以传递到child,不能传递到plug
2、修改child的值,可以传递到child 和 app
3、修改plug插件的值,可以传递到child 和 app
继续解决问题
修改child的 data 属性为computed 属性
此时app, child, plug数据都可以正常传递
<template>
<div> <p>child.vue 子组件:{{innerVlaue}}</p> <button @click="changeValue">子组件+1</button> <plug v-model="innerVlaue" />
</div>
</template>
<script>
import plug from "./Plug.vue";
export default {
props: ["value"], computed: { innerVlaue:{ get(){ return this.value }, set(newValue){ this.$emit("input", newValue) } }
}, components: { plug
}, methods: { changeValue() { this.innerVlaue++; }
}
};
</script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
至此,子孙三代的数据传递正常,warn问题解决
自始至终,app, plug 的代码都没有做修改,只是修改了child 中的data属性或computed
所以,要正常通信,需要修改中间数据层的传递方式,既要考虑父级组件数据流入,也要兼顾子组件的事件传入
最后在child中使用 computed 计算属性完成了承上启下数据传递
v-model同样可以使用.sync实现,只是写法不一样
如果子组件不需要获取父组件数据,父组件直接可以和插件通信, 可以参看文章:
文章来源: pengshiyu.blog.csdn.net,作者:彭世瑜,版权归原作者所有,如需转载,请联系作者。
原文链接:pengshiyu.blog.csdn.net/article/details/102912298
- 点赞
- 收藏
- 关注作者
评论(0)