vue组件通信进阶

序言:我们都知道vue父子组件通信主要通过props和事件,那还知道其他形式的通讯方式吗?本文将一一为你揭晓。

1、sync修饰符+this.$emit(‘update:属性名’, data)

1.1、sync修饰符的作用

在Vue中,子父组件最常用的通信方式就是通过props进行数据传递,props值只能在父组件中更新并传递给子组件,在子组件内部,是不允许改变传递进来的props值,这样做是为了保证数据单向流通。但有时候,我们会遇到一些场景,需要在子组件内部改变props属性值并更新到父组件中,这时就需要用到.sync修饰符。

如果我们在子组件中直接修改props中的属性值,将会报以下错误:

《vue组件通信进阶》

报错的大概意思就是:不允许直接修改props里面的属性值。

这里可以参考一篇文章:https://blog.csdn.net/XuM2222…

1.2、利用sync修饰符实现双向数据绑定

父组件:通过给绑定属性添加sync修饰符将值传递给子组件,父组件值改变,子组件随着改变。
子组件:通过this.$emit(‘update:属性名’, data)来改变props属性值并更新父组件对应的值。

<template>
  <div @click="click2change">
    点击加一{{foo}}
    <my-checkbox :checked.sync="foo"></my-checkbox>
  </div>
</template>

<script>
import Vue from 'vue';
// 组件通信: props,事件,provide|inject,vuex, vuebus,。。。

const myCheckbox = Vue.component('my-checkbox', {
  props: {
    value: {
      type: String,
      default: 'testvalue'
    },
    checked: {
      type: Number,
      default: 0
    }
  },
  methods: {
    changeValue() {
      //this.checked -= 2;//会报刚刚说的错误,不能直接修改props属性值
      this.$emit("update:checked", this.checked - 2);
    }
  },
  template: `
    <div>
      <div @click.stop="changeValue">checked: {{checked}}</div>
    </div>
  `
});

export default {
  name: 'list',
  components: {
    myCheckbox,
  },
  data() {
    return {
      foo: 1
    }
  },
  methods: {
    click2change() {
      this.foo += 1;
    }
  }
}
</script>

结果运行:
《vue组件通信进阶》

2、自定义组件v-model+this.$emit(‘自定事件名’, data)

2.1、v-model语法糖

《vue组件通信进阶》

2.2、自定义组件v-model

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

现在在这个组件上使用 v-model 的时候:

<base-checkbox v-model="lovingVue"></base-checkbox>

这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 <base-checkbox> 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。

注意:你仍然需要在组件的 props 选项里声明 checked 这个 prop。

2.3、使用自定义组件v-model实现双向数据绑定

父组件:通过v-model向子组件传值,并监听自定义函数更新值。
子组件:通过model选项自定义绑定属性名和方法,使用$emit触发自定义方法更新父组件的值。

<template>
  <div @click="click2change">
    点击加一{{foo}}
    <my-checkbox v-model="foo"></my-checkbox>
  </div>
</template>

<script>
import Vue from 'vue';

// 组件通信: props,事件,provide|inject,vuex, vuebus,。。。

const myCheckbox = Vue.component('my-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    //需要在组件的 props 选项里声明 checked 这个 prop
    checked: {
      type: Number,
      default: 0
    }
  },
  methods: {
    changeValue() {
      this.$emit("change", this.checked - 1);
    }
  },
  template: `
    <div>
      <div @click.stop="changeValue">checked: {{checked}}</div>
    </div>
  `
});

export default {
  name: 'list',
  components: {
    myCheckbox,
  },
  data() {
    return {
      foo: 1
    }
  },
  methods: {
    click2change() {
      // debugger
      this.foo += 1;
    }
  }
}
</script>

运行结果:

《vue组件通信进阶》

3、value方式+this.$emit(‘input’, data)

这种方式实现双向数据绑定是基于v-model语法糖

<template>
  <div @click="click2change">
    点击加一{{foo}}
    <my-checkbox v-model="foo"></my-checkbox>
  </div>
</template>

<script>
import Vue from 'vue';

// 组件通信: props,事件,provide|inject,vuex, vuebus,。。。

const myCheckbox = Vue.component('my-checkbox', {
  props: {
    value: {
      type: Number,
      default: 0
    }
  },
  methods: {
    changeValue() {
      this.$emit("input", this.value - 1);
    }
  },
  template: `
    <div>
      <div @click.stop="changeValue">value: {{value}}</div>
    </div>
  `
});

export default {
  name: 'list',
  components: {
    myCheckbox,
  },
  data() {
    return {
      foo: 1
    }
  },
  methods: {
    click2change() {
      // debugger
      this.foo += 1;
    }
  }
}
</script>

运行结果:
《vue组件通信进阶》

4、总结

无论是上面哪种双向数据绑定的方式,基本原理还是基于props和事件,只是形式上的改变,本质没有变。

    原文作者:ToSmile
    原文地址: https://segmentfault.com/a/1190000020206522
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞