序言:我們都知道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和事件,只是形式上的改變,本質沒有變。