Vue组件间传值,默认遵循单向下行绑定原则

360截图20190919081130245.jpg
prop传值的本质,是传递的引用。内外组件同一参数指向同一个内存区域,所以数据可以同步。
如果遇到在子组件内部需要更改prop传值,可以按照如下思路来巧妙处理:
子组件sel-user代码如下:
<template>
<div class="sel-user">
<!--侧边栏导航-选择用户-->
<el-dialog :visible.sync="cVisible" :title="title" :close-on-click-modal="false" width="880px">
<el-row style="padding:10px 0; border-top:1px solid #eee;">
<el-col>
<el-button size="small" @click="cancel" class="fr marr15">取 消</el-button>
<el-button type="primary" size="small" @click="sure" class="fr marr10">确 定</el-button>
</el-col>
</el-row>
</el-dialog>
</div>
</template>
<script>
export default {
name: "sel-user",
props: {
title: { type: String, required: false, default: "选择用户" },
visible: { type: Boolean, required: false, default: false }
},
data: function() {
return {
cVisible: this.visible
};
},
watch: {
visible(newVal) {
this.cVisible = newVal;
}
},
methods: {
sure: function(flag) {
this.cVisible = false;
this.$emit("on-selected", this.cData);
},
cancel: function(flag) {
this.cVisible = false;
}
}
};
</script>
可以看到,接受外部的两个prop参数,title和visible两个参数,title是仅用于显示,visible是需要修改用于切换dialog隐藏/显示。所有,需要给visible参数创建一个内部副本cVisible,实现和visible解绑,支持修改。完美避开单向数据流。
父组件中调用代码:
<template>
<div>
<sel-user ref="seluser" :visible="dialog.user" @on-selected="selUser"></sel-user>
<el-button type="success" class="fl" @click="openSelUser">添加用户</el-button>
</div>
</template>
<script>
import selUser from "@/views/components/sel-user";
export default {
name: "admin_module_public",
components: { selUser},
data() {
return {
dialog: {
user: false
}
}
},
methods: {
openSelUser: function() {
this.dialog.user = true;
}
}
}
</script>
实现效果:

1.gif
点击添加用户按钮,改变
dialog.user=true,传入sel-user组件:visible="dialog.user"参数,sel-user显示出来。但是发现当弹窗关闭后,再次点击父组件中的添加用户按钮,弹窗丝毫没有反应,控制台也没有报错。原因是在sel-user中cVisible副本实现对visible值的watch监听,但是外部dialog.user的值并没有改变,没有触发监听,所以内部cVisible永远都等于false;解决思路有2种:
1、添加一个专用于触发监听的prop参数
2、在sel-user中创建一个
show方法,用于直接修改cVisible参数
下面演示方案2实现方式
sel-user组件中methods代码,其他代码都不用动。
...
methods: {
show() {
this.cVisible = true;
},
sure: function(flag) {
this.cVisible = false;
this.$emit("on-selected", this.cData);
},
cancel: function(flag) {
this.cVisible = false;
}
}
...
父组件调用方式:
...
openSelUser: function() {
this.$refs.seluser.show();
},
...
这样,父组件中直接修改子组件中cVisible的值,子组件中可以直接去掉prop -> visible。
Vue官网提供的规避单项数据流的解决方案:规避单向数据流

image.png