Vue子孙三代的三级组件通信
2023-09-14 09:07:19 时间
1、首先是一个简单的示例
三个文件
app.vue # 自定义的业务,调用自己封装的组件child.vue
child.vue # 自己封装的第三方组件plug.vue,便于上层调用
plug.vue # 第三方组件,提供v-model数据绑定
调用层次结构
app -> child -> plug
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>
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>
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>
修改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"
原因是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、修改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>
至此,子孙三代的数据传递正常,warn问题解决
自始至终,app, plug 的代码都没有做修改,只是修改了child 中的data属性或computed
所以,要正常通信,需要修改中间数据层的传递方式,既要考虑父级组件数据流入,也要兼顾子组件的事件传入
最后在child中使用 computed 计算属性完成了承上启下数据传递
v-model同样可以使用.sync实现,只是写法不一样
如果子组件不需要获取父组件数据,父组件直接可以和插件通信, 可以参看文章:
相关文章
- Vue_(组件通讯)动态组件
- vue父组件传字符串到子组件不需要写 v-bind 绑定或语法糖 :
- vue 注册全局组件
- vue全局组件和局部组件
- 浅谈 vue实例 和 vue组件
- [Vue @Component] Define Props on a Vue Class with vue-property-decorator
- vue-resource插件使用
- 浅谈 vue实例 和 vue组件
- vue中8种组件通信方式, 值得收藏!
- vue.js3:pdf文件转图片(pdfjs-dist@2.14.305 / vue@3.2.37)
- vue.js 3.2.22:平滑回到顶部
- 【视频】vue组件的全局注册
- Vue实现全局异常处理的几种方案
- vue-cli创建的项目的目录结构及说明
- vue - 自定义组件使用v-model属性的具体说明,重点说明参数的定义
- vue - vant组件库 - card组件 修改 thumb属性的图片 参数后不及时刷新解决
- CDN方式Vue组件注册
- Vue中组件化编码使用(实战练习一)
- vue用阿里云oss上传图片使用分片上传只能上传100kb以内的解决办法
- 194: vue+openlayers 根据卫星lat,lon,alt,俯仰角,方位角,绘制地面的拍摄的区域
- 089:vue+openlayers列表与图层 提示交互( 代码示例 )
- 017:vue+openlayer实现旋转地图效果( 代码示例 )
- 075:vue+openlayers: Drag-and-Drop拖拽文件解析显示图形(代码示例)
- 声纹可视化工具:wavesurfer.js---在Vue中使用音频声纹可视化插件wavesurfer.js【已封装成组件有完整demo实例附完整代码】
- Vue 进阶组件实战应用 -- 父子组件传值的应用实例(子父组件传值的两种触发方式)
- Vue 组件的定义、组件的使用、什么是路由、路由的定义和使用、nrm的安装使用