本篇文章主要介紹父子組件傳值,組件的數據雙向綁定鹃觉。
1. 基礎父子組件傳值
父子組件傳值,這是Vue組件傳值最常見睹逃,最基礎的傳值方法盗扇。
父組件向子組件傳值使用Props,子組件定義期望接收傳值的名字、類型沉填、默認值等等疗隶,父組件Props值的改變會自動同步到子組件。
子組件向父組件傳值使用事件觸發(fā),即使用$emit
注冊事件翼闹,在父組件觸發(fā)斑鼻,這個事件可以攜帶值,而且一個事件的觸發(fā)本身就是在傳遞信息橄碾。
代碼實現:
//父組件
<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>
由于父組件的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>
我們沒用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>
由此我們實現了Com2這個組件的v-model
,改變的是取消了Com2的事件監(jiān)聽@input
,Propsvalue
迹蛤,換來了v-model
民珍,這個簡化的過程就是語法糖襟士。v-model
會自動處理那些注釋掉的操作,即v-model
會自動處理一個組件的input
事件和value
Props嚷量,讓兩者綁定陋桂。
input的v-model已經實現,我們來說一說自定義組件的v-model津肛,v-model
會檢測組件的input
事件和value
Props章喉,這顯然是不行的,自定義組件需要的不一定是這兩個東西,幸好子組件里還有一個屬性mode
身坐,可以用來改變v-model
默認監(jiān)聽的Props和event秸脱,代碼如下:
export default {
name: 'Com2',
model: {
//默認監(jiān)聽的事件和prop
// event: 'input',
// prop: 'value',
//自定義的監(jiān)聽子組件觸發(fā)事件和傳進去的prop
event: 'change',
prop: 'datas'
},
//其他代碼
}
這時在父組件使用子組件的時候,在子組件使用v-model
就會自動處理change
事件和datas
Props部蛇,這樣就可以隨意定義想要的雙向綁定屬性了摊唇,但是一個組件只能有一個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
修飾符雙向綁定。