vue組件通信進階

序言:我們都知道vue父子組件通信主要通過props和事件,那還知道其他形式的通訊方式嗎?本文將一一爲你揭曉。

1、sync修飾符+this.$emit('update:屬性名', data)

1.1、sync修飾符的作用

在Vue中,子父組件最常用的通信方式就是通過props進行數據傳遞,props值只能在父組件中更新並傳遞給子組件,在子組件內部,是不允許改變傳遞進來的props值,這樣做是爲了保證數據單向流通。但有時候,我們會遇到一些場景,需要在子組件內部改變props屬性值並更新到父組件中,這時就需要用到.sync修飾符。

如果我們在子組件中直接修改props中的屬性值,將會報以下錯誤:

圖片描述

報錯的大概意思就是:不允許直接修改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>

結果運行:
圖片描述

2、自定義組件v-model+this.$emit('自定事件名', data)

2.1、v-model語法糖

圖片描述

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>

運行結果:

圖片描述

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>

運行結果:
圖片描述

4、總結

無論是上面哪種雙向數據綁定的方式,基本原理還是基於props和事件,只是形式上的改變,本質沒有變。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章