美文网首页
Vue父子组件通信和双向绑定

Vue父子组件通信和双向绑定

作者: Wermdany | 来源:发表于2019-07-29 17:09 被阅读0次

    本篇文章主要介绍父子组件传值,组件的数据双向绑定。

    1. 基础父子组件传值

    父子组件传值,这是Vue组件传值最常见,最基础的传值方法。
    父组件向子组件传值使用Props,子组件定义期望接收传值的名字、类型、默认值等等,父组件Props值的改变会自动同步到子组件。
    子组件向父组件传值使用事件触发,即使用$emit注册事件,在父组件触发,这个事件可以携带值,而且一个事件的触发本身就是在传递信息。
    代码实现:

    //父组件
    <template>
      <div id="parent">
      父组件的text:{{text}}
        <Child :text="text" @changeText="prentEvent"></Child>
      </div>
    </template>
    <script>
    export default {
      components: {
        Child: () => import('@/components/Child')
       },
      data() {
        return {
          text: 'a'
        }
      },
      methods: {
        prentEvent(value) {
          this.text = value
        },
    }
    </script>
    
    //子组件
    <template>
      <div class="child">
        <p>子组件text:{{text}}</p>
        <button @click="changeParent">改变父组件text</button>
      </div>
    </template> 
    <script>
    export default {
      name: 'Child',
      props: {
        text: {
          type: String,
          required: true
        }
      },
      data() {
        return {}
      },
      methods: {
        changeParent() {
          this.$emit('changeText', 'b')
        },
      },
    }
    </script>
    
    1.gif

    由于父组件的Props改变会自动传递到子组件,所以会同步变化。

    2. 父子组件传值的双向绑定

    上述例子有点双向绑定的意思,但这并不是双向绑定,Vue的数据都是单向流动的,而且Vue中从来就没有任何的双向绑定,那些双向绑定只是语法糖而已
    我们都知道v-model可以用在 input标签上,实现双向绑定,其实Vue已经把input标签进行了修改,也就是 input标签已经是一个Vue的内置组件了,同样的内置组件还有很多,比如,用于缓存的keep-alive,用于路由链接的router-like,用于路由视图展示的router-view等等。
    实现一个自定组件的v-model之前,我们先实现一个双向绑定,代码如下:

    //Com1
    <template>
      <div class="com1">
        Com1:
        <input type="text" :value="value" @input="changeSelf" />
        <Com2 :value="value" @input="changes"></Com2>
      </div>
    </template>
    <script>
    export default {
      name: 'Com1',
      components: {
        Com2: () => import('./Com2')
      },
      data() {
        return {
          value: ''
        }
      },
      methods: {
        changes(values) {
          this.value = values
        },
        changeSelf(e) {
          this.value = e.target.value;
        },
      },
    }
    </script>
    
    //Com2
    <template>
      <div class="com2">
        Com2:
        <input type="text" :value="value" @input="Com2Input" />
      </div>
    </template>
    <script>
    export default {
      name: 'Com2',
      props: {
        value: {
          type: String,
          required: true,
        }
      },
      methods: {
        Com2Input(e) {
          this.$emit('input', e.target.value)
        }
      },
    }
    </script>
    
    2.gif
    我们没用Vue的v-model同样可以实现数据的双向绑定。我们如何改造成v-model呢?只能改变父组件Com1,子组件不能更改,代码如下:
    //Com1
    <template>
      <div class="com1">
        Com1:
        <!--下面这行改变是为了精简代码,使用input标签的v-model--!>
        <!-- <input type="text" :value="value" @input="changeSelf" /> -->
        <input type="text" v-model="value" />
        <!-- <Com2 :value="value" @input="changes"></Com2> -->
        <Com2 v-model="value"></Com2>
      </div>
    </template>
    <script>
    export default {
      name: 'Com1',
      components: {
        Com2: () => import('./Com2')
      },
      data() {
        return {
          value: ''
        }
      },
      methods: {
        // changes(values) {
        //   this.value = values
        // },
        // changeSelf(e) {
        //   this.value = e.target.value;
        // },
      },
    }
    </script>
    
    3.gif

    由此我们实现了Com2这个组件的v-model,改变的是取消了Com2的事件监听@input,Propsvalue,换来了v-model,这个简化的过程就是语法糖。v-model会自动处理那些注释掉的操作,即v-model会自动处理一个组件的input事件和valueProps,让两者绑定。
    input的v-model已经实现,我们来说一说自定义组件的v-model,v-model会检测组件的input事件和valueProps,这显然是不行的,自定义组件需要的不一定是这两个东西,幸好子组件里还有一个属性mode,可以用来改变v-model默认监听的Props和event,代码如下:

    export default {
      name: 'Com2',
      model: {
        //默认监听的事件和prop
        // event: 'input',
        // prop: 'value',
        //自定义的监听子组件触发事件和传进去的prop
        event: 'change',
        prop: 'datas'
      },
      //其他代码
    }
    

    这时在父组件使用子组件的时候,在子组件使用v-model就会自动处理change事件和datasProps,这样就可以随意定义想要的双向绑定属性了,但是一个组件只能有一个v-model
    在Vue 2.3.0 中加入了.sync 修饰符,也是用来处理双向绑定的,封装流程和v-model类似,在子组件需要这样操作,代码如下:

    //在需注册事件的地方这样写
    this.$emit('update:datas', newDatas)
    //在父组件调用这个子组件的时候这样写
    <Com3
      v-bind:datas="datas"
      v-on:update:datas="datas = $event"
    ></Com3>
    //使用.sync 修饰符简化为
    <Com3 :datas.sync="datas"></Com3>
    //子组件的事件注册不改动
    

    这样同样可以实现双向绑定,一个组件可以有多个.sync修饰符双向绑定。

    相关文章

      网友评论

          本文标题:Vue父子组件通信和双向绑定

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