vue 通过 v-model 实现父子组件的双向数据绑定

单向数据流
单向数据流是Vue组件一个非常明显的特征,不应该在子组件中直接修改props的值

  • 如果传递的props仅仅用作展示,不涉及修改,则在模板中直接使用即可
  • 如果需要对props的值进行转化然后展示,则应该使用computed计算属性
  • 如果props的值用作初始化,应该定义一个子组件的data属性并将props作为其初始值

组件之间的通信

  • 父子组件的关系可以总结为 props 向下传递,事件event向上传递
  • 祖先组件和后代组件(跨多代)的数据传递,可以使用provideinject来实现
  • 跨组件或者兄弟组件之间的通信,可以通过eventBus或者vuex等方式来实现

通过v-model语法糖实现父子组件的数据双绑

Vue内置了v-model指令,v-model是一个语法糖,默认会利用名为 valueprop 和名为inputeventmodel属性可以自定义propevent

  model: {
    prop: 'msg',
    event: 'cc'
  },

父组件test的值将会传入这个名为msg的prop
同是当aa组件触发click事件并附带一个新的值得时候,父组件的test属性将会被更新

//父组件
<template>
  <div>
    <aa class="abc" v-model="test" ></aa> 
    {{'外面的值:' + test}}
    <button @click="fn">外面改变里面</button> 
  </div>
</template>

<script>
  import aa from './aa'
  export default {
    data () {
      return {
        test: ''
      }
    },
    methods: {
      fn () {
        this.test += 1 
      }
    },
    components:{
      aa
    }
  }
</script>
//子组件
<template>
  <div>
    {{'里面的值:'+ msg}}
    <button @click="fn2">里面改变外面</button>
  </div>
</template>

<script>
  export default {
    /**
     * 使用model, 这里有2个属性
     * prop属性说,父组件的v-model的值就是msg
     * event说,我emit ‘cc’ 的时候,父组件v-model的值就是参数的值
     */
    model: {
      prop: 'msg',
      event: 'cc'
    },
    props: {
      msg: ''
    },
    methods: {
      fn2 () {
        this.$emit('cc', this.msg+2)
      }
    }
  }
</script>
//使用默认prop、event的子组件
<template>
  <div>
    {{'里面的值:'+ value}}
    <button @click="fn2">里面改变外面</button>
  </div>
</template>

<script>
  export default {
    /**
     * 默认会利用名为 value 的 prop 和名为input的event
     */
    props: {
      value: ''
    },
    methods: {
      fn2 () {
        this.$emit('input', this.value+2)
      }
    }
  }
</script>

父子组件中需要多个双向绑定写法

//父组件
<template>
  <div>
    <aa class="abc" v-model="sObj" ></aa> 
    {{'外面的值:' + test+','+touchStartTest}}
    <button @click="fn" @touchstart="fnTouchstart">外面改变里面</button> 
  </div>
</template>

<script>
  import aa from './v-model-child'
  export default {
    data () {
      return {
            test: '',
            touchStartTest:'',
            sObj:'',
      }
    },
    watch:{
        test:function(val){
            this.sObj = JSON.stringify({test:val,touchStartTest:this.touchStartTest})
        },
        touchStartTest:function(val){
            this.sObj = JSON.stringify({test:this.test,touchStartTest:val})
        },
        sObj:function(val){
            this.test = JSON.parse(this.sObj).test;
            this.touchStartTest = JSON.parse(this.sObj).touchStartTest;
        }
    },
    methods: {
      fn () {
        this.test += 1 
      },
      fnTouchstart(){
          this.touchStartTest+=5
      }
    },
    components:{
      aa
    }
  }
</script>
//子组件
<template>
  <div>
    {{'里面的值:'+ jsonMsg.test+','+jsonMsg.touchStartTest}}
    <button @click="fn2" @touchstart="fnTouchstart2">里面改变外面</button>
  </div>
</template>

<script>
  export default {
    /**
     * 使用model, 这里有2个属性
     * prop属性说,父组件的v-model的值就是msg
     * event说,我emit ‘cc’ 的时候,父组件v-model的值就是参数的值
     */
    model: {
      prop: 'msg',
      event: 'cc'
    },
    props:['msg'],
    computed:{
        jsonMsg(){
            return this.msg=='' ? {test:'',touchStartTest:''} : JSON.parse(this.msg);
        }
    },
    methods: {
      fn2 () {
        this.$emit('cc', JSON.stringify({test:this.jsonMsg.test+2,touchStartTest:this.jsonMsg.touchStartTest}))
      },
      fnTouchstart2(){
        this.$emit('cc', JSON.stringify({test:this.jsonMsg.test,touchStartTest:this.jsonMsg.touchStartTest+6}))
      }
    }
  }
</script>

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值