Vue | 自定义组件数据双向流动

16 篇文章 0 订阅

现有一个查询页面 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)
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值