美文网首页
通过 v-model 实现父子组件的双向数据绑定

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

作者: 简单tao的简单 | 来源:发表于2019-07-23 21:41 被阅读0次

    单向数据流
    单向数据流是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>
    

    相关文章

      网友评论

          本文标题:通过 v-model 实现父子组件的双向数据绑定

          本文链接:https://www.haomeiwen.com/subject/ylqzlctx.html