现有一个查询页面 index.vue ,组成架构如下
需求:在表单组件中新增一个下拉框组件A.vue,对地区(area)进行选择,并做到数据能双向流动, 由于提交表单是在query,而下拉框数据放在A中,因此A中下拉框数据变化要更新到父组件的表单数据中。
实现
表单组件query.vue:
<el-form :model="queryForm" :rules="rules" ref="queryForm" label-width="120px">
<!-- <el-form-item> .... </el-form-item> !-->
<el-form-item label="地区">
<select-area v-model="area" clearable></select-area>
</el-form-item>
</el-form>
<script>
data(){
return{
area: '' //表单数据
}
}
</script>
下拉框组件A.vue
<template>
<el-select v-model="init_value" placeholder="请选择" filterable>
<el-option
v-for="(item, index) in areaList"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
<script>
export default {
props:{
value:{
type: String,
default:''
}
},
data(){
return{
areaList:[],
init_value: this.value
}
},
watch: {
// 监听prop中的value
// 即是监听父组件中area的变化
value(newVal){
this.init_value = newVal;
},
// 监听子组件A中init_value的改变
// 因为父组件中用v-model绑定area,v-model是@input + :value的语法糖
// 因此可以emit('input',newVal)把新的所选项值传给父组件,更新父组件的area
init_value(newVal){
this.$emit('input',newVal)
}
},
mounted(){
this.areaList = [
{
label: '中国',
value: 'China'
},
{
label: '美国',
value: 'US'
}
]
}
}
</script>
<style>
</style>
总结:
- 要用一个init_value来接受prop的引用,不能直接修改prop的value,会引起警告。
- 监听到子组件init_value数据更新后用 emit(‘input’,val) 来触发父组件的v-model,从而改变父组件area的值
Vue中的修饰符sync也可以做到双向绑定
父组件
<son v-bind:title.sync="title"></son>
子组件
情况1:为input类型
<div class="son">
<input v-bind:value="title" v-on:input="change1">
</div>
change1(e){
this.title = e.target.value;
this.$emit('update:title',this.title)
}
情况2:为普通类型
<div class="son">
<h1 v-text="title"></h1>
</div>
mounted() {
let _self = this;
setTimeout(()=>{
_self.title = 'hshsh';
_self.$emit('update:title',_self.title)
},1000)
}