1、組件間的通訊vue
組件實例的做用域是孤立的;這意味着不能而且不該該在子組件的模板內直接引用父組件的數據。可是父子組件之間須要通訊:父組件要給子組件傳遞數據,子組件須要將它內部發生的事情告知給父組件。數組
在 Vue.js 中,父子組件的關係能夠總結爲 props down, events up 。父組件經過 props 向下傳遞數據給子組件,子組件經過 events 給父組件發送消息。以下圖所示:this
2、 Prop — 父組件傳遞數據給子組件spa
prop 是父組件用來傳遞數據的一個自定義屬性。子組件須要顯式地用 props 選項聲明 「prop」:3d
Vue.component('child', {component
// 聲明 props對象
props: ['message'],索引
// 就像 data 同樣,prop 能夠用在模板內接口
// 一樣也能夠在 vm 實例中像 「this.message」 這樣使用事件
template: '<span>{{ message }}</span>'
})
2.1 簡單的傳值
注意:HTML 特性不區分大小寫。當使用非字符串模版時,prop的名字形式會從 camelCase 轉爲 kebab-case(短橫線隔開)。
2.2 父組件傳值給子組件,動態綁定
運行結果:
父組件傳遞數據給子組件圖解:
2.3 prop默認是單向綁定
當父組件的屬性變化時,將傳導給子組件,可是反過來不會。這是爲了防止子組件無心修改了父組件的狀態。
案例驗證:
運行結果:
結論:在vuejs2.0中,任何試圖在組件內修改經過props傳入的父組件數據都被認爲是anti-pattern的。
3、自定義事件
咱們知道,父組件是使用 props 傳遞數據給子組件,但若是子組件要把數據傳遞回去,應該怎樣作?那就是自定義事件!
每一個 Vue 實例都實現了事件接口(Events interface),即:
使用 $on(eventName) 監聽事件
使用 $emit(eventName) 觸發事件
另外,父組件能夠在使用子組件的地方直接用 v-on 來監聽子組件觸發的事件。
一個簡單的官方案例幫助咱們來理解:
運行結果:子組件已經和它外部徹底解耦了。它所作的只是觸發一個父組件關心的內部事件。
4、Slot插槽 — 實現內容分發
父組件模板的內容在父組件做用域內編譯;子組件模板的內容在子組件做用域內編譯
上面話的意思在於:在子組件中定義的數據,只能用在子組件的模板;在父組件中定義的數據,只能用在父組件的模板。若是父組件的數據要在子組件中使用,則須要子組件定義props。
4.1 什麼是slot?
slot的意思是插槽,其目的在於讓組件的可擴展性更強。打個比方說:假如父組件須要在子組件內放一些DOM,那麼這些DOM是顯示、不顯示、在哪一個地方顯示、如何顯示,就是slot分發負責的。
(1) 匿名solt
下面這個示例是一個匿名slot,它只能表示一個插槽:
結合上述案例,咱們再進一步來了解:好比咱們定製了一個button組件,在根組件裏註冊爲vButton,從而複用。那麼各個button上的文字確定是不一樣的,可是這些文字大部分狀況下也是不須要動態更新的,那麼就沒必要用props之類的方法從根組件向子組件傳遞文字,直接用slot便可。
(2) 實名solt
假設你的電腦主板上的各類插槽,有插CPU的,有插顯卡的,有插內存的,有插硬盤的,因此假設有個組件是computer,其模板是:
<template id="computer">
<div>
<slot name="CPU">這兒插你的CPU</slot>
<slot name="GPU">這兒插你的顯卡</slot>
<slot name="Memory">這兒插你的內存</slot>
<slot name="Hard-drive">這兒插你的硬盤</slot>
</div>
</template>
那麼,你想要配置一臺電腦,就能夠這麼寫:
<computer>
<div slot="CPU">Intel Core i7</div>
<div slot="GPU">GTX980Ti</div>
<div slot="Memory">Kingston 32G</div>
<div slot="Hard-drive">Samsung SSD 1T</divt>
</computer>
具體代碼以下:
5、父子組件之間相互訪問
在開發中,組件之間須要相互訪問。好比:父組件訪問子組件,子組件訪問父組件,或者是子組件訪問根組件。
針對這種狀況,Vue.js提供瞭如下API:
父組件訪問子組件:使用$children或$refs (一個對象,其中包含了全部擁有 ref 註冊的子組件)
子組件訪問父組件:使用$parent
子組件訪問根組件:使用$root
5.1 $children
運行結果:
在父組件中,經過this.$children能夠訪問子組件;this.$children是一個數組,它包含全部子組件的實例。
5.2 $refs
在子組件上使用v-ref指令,能夠給子組件指定一個索引ID;經過這個ID咱們能夠拿到這個組件。
<template id="parent-component">
<div>
<first-component ref="fc1"></first-component>
<second-component ref="fc2"></second-component>
<button @click="printAllChildComponent">輸出子組件</button>
</div>
</template>
在父組件中,則經過```$refs.索引ID```訪問子組件的實例。
5.3 $parent
<template id="first-component">
<div>
<h2>{{ content }}</h2>
<button @click="printParentComponent">獲取父組件</button>
</div>
</template>
'first-component': {
template: '#first-component',
data:function () {
return {
content: '我是子組件1'
}
},
methods: {
printParentComponent: function () {
console.log(this.$parent.$el);
}
}
}
運行結果:
注意事項:
儘管子組件能夠訪問父鏈上任意的實例,不過子組件應當避免直接依賴父組件的數據,儘可能顯式地使用 props 傳遞數據。
另外,在子組件中修改父組件的狀態是很是不提倡的作法,由於:這讓父組件與子組件緊密地耦合;只看父組件,很難理解父組件的狀態。由於它可能被任意子組件修改!理想狀況下,只有組件本身能修改它的狀態。