使用场景:
vue的prop是单向下行绑定:父级prop的更新会带动子组件更新,但是反过来不行,如果需要更新父级数据变化,一般是子组件通过 $emit 发射自定义事件方法,父组件进行监听这个事件方法,从而实现更新数据。
有些情况,我们需要对prop进行“双向绑定”,例如,封装了一个单选radio子组件,父组件传过来初始绑定的值,在radio值发生变化时,此时父组件绑定的值并未发生更新。为了在radio值发生变化时,父组件可以同时更新,这时可以用 .sync 或v-model解决这个问题。
.sync方式
formRadio子组件:
<template>
<div class="elradio">
<el-radio
:disabled="disabled"
v-for="(item,index) in options"
:key="index"
v-model="val"
:label="item[showKey.value]"
@change="change">
{
{ item[showKey.label] }}
</el-radio>
</div>
</template>
<script>
export default {
name : 'formRadio',
props : {
value : {
type : String | Number, //父组件传过来绑定(v-model)的值
default(){
return '';
}
},
showKey : { //展示数据对象对应label和value对应的key值
type : Object,
default(){
return {
label : 'label',
value : 'value'
}
}
},
parentOptions : { //父组件传过来的options枚举值
type : Array,
default(){
return []
}
},
dataType : {
type : String, //父组件没有传枚举值,可以通过dataType使用自定义的一些枚举值
default(){
return ''
}
},
disabled : { //是否禁用
type : Boolean,
default(){
return false;
}
},
},
data(){
return {
val : '', //单选按钮绑定的值
options : [], //单选按钮要展示的枚举值
sexType : [
{
value: '1',
label: '男'
},
{
value: '2',
label: '女'
},
]
}
},
mounted(){
if (this.parentOptions) { //父组件传枚举值,就展示父组件的
this.options = this.parentOptions;
}
if (this.dataType) { //父组件没传枚举值,通过传dataType使用内部自定义的枚举值
this.options = this[this.dataType]
}
if(this.value){ //初始化单选按钮绑定的值
this.val = this.value;
}
},
methods : {
change(currentRadioVal){ //值发生变化后,同时更新父组件绑定的值
this.$emit('update:value', currentRadioVal); //更新父组件初始化传过来绑定的值(.sync方式传值时)
}
}
}
</script>
<style scoped>
.elradio{
text-align: left;
width: 100%;
}
</style>
父组件:
<formRadio :value.sync='forma.sex' :dataType="'sexType'"></formRadio>
v-model方式
父子组件同时使用v-model指令,父组件v-model绑定的值会传给子组件v-model绑定的props中的值。即代替了之前 :value.sync 方式传值,直接使用v-model传值。此时,子组件唯一不同的地方是更新父组件值的方式发生了变化。
formRadio子组件:
<template>
<div class="elradio">
<el-radio
:disabled="disabled"
v-for="(item,index) in options"
:key="index"
v-model="val"
:label="item[showKey.value]"
@change="change">
{
{ item[showKey.label] }}
</el-radio>
</div>
</template>
<script>
export default {
name : 'formRadio',
props : {
value : {
type : String | Number, //父组件传过来绑定(v-model)的值
default(){
return '';
}
},
showKey : { //展示数据对象对应label和value对应的key值
type : Object,
default(){
return {
label : 'label',
value : 'value'
}
}
},
parentOptions : { //父组件传过来的options枚举值
type : Array,
default(){
return []
}
},
dataType : {
type : String, //父组件没有传枚举值,可以通过dataType使用自定义的一些枚举值
default(){
return ''
}
},
disabled : { //是否禁用
type : Boolean,
default(){
return false;
}
},
},
data(){
return {
val : '', //单选按钮绑定的值
options : [], //单选按钮要展示的枚举值
sexType : [ //自定义的枚举值
{
value: '1',
label: '男'
},
{
value: '2',
label: '女'
},
]
}
},
mounted(){
if (this.parentOptions) { //父组件传枚举值,就展示父组件的
this.options = this.parentOptions;
}
if (this.dataType) { //父组件没传枚举值,通过传dataType使用内部自定义的枚举值
this.options = this[this.dataType]
}
if(this.value){ //初始化单选按钮绑定的值
this.val = this.value;
}
},
methods : {
change(currentRadioVal){ //值发生变化后,同时更新父组件绑定的值
//this.$emit('update:value', currentRadioVal); //更新父组件初始化传过来绑定的值(.sync方式传值时)
this.$emit('input', currentRadioVal); //更新父组件初始化传过来绑定的值(v-model方式传值时)
}
}
}
</script>
<style scoped>
.elradio{
text-align: left;
width: 100%;
}
</style>
父组件:此时,父组件的传值方式变为了v-model传值方式。
<formRadio v-model='forma.sex' :dataType="'sexType'"></formRadio>