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

2019-07-23  本文已影响0人  简单tao的简单

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

组件之间的通信

通过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>
上一篇 下一篇

猜你喜欢

热点阅读