本文爲轉載,原文:Vue學習筆記入門篇——組件的通信數組
組件意味着協同工做,一般父子組件會是這樣的關係:組件 A 在它的模版中使用了組件 B。它們之間必然須要相互通訊:父組件要給子組件傳遞數據,子組件須要將它內部發生的事情告知給父組件。然而,在一個良好定義的接口中儘量將父子組件解耦是很重要的。這保證了每一個組件能夠在相對隔離的環境中書寫和理解,也大幅提升了組件的可維護性和可重用性。
在 Vue 中,父子組件的關係能夠總結爲 props down, events up。父組件經過 props 向下傳遞數據給子組件,子組件經過 events 給父組件發送消息。看看它們是怎麼工做的。app
組件實例的做用域是孤立的。這意味着不能 (也不該該) 在子組件的模板內直接引用父組件的數據。要讓子組件使用父組件的數據,咱們須要經過子組件的 props 選項。
子組件要顯式地用 props 選項聲明它期待得到的數據:函數
<div id="example"> <input v-model="parentMsg"><br> <child :my-message="parentMsg"></child> </div>
Vue.component('child', { props:['myMessage'], template:'<span>{{myMessage}}</span>' }) new Vue({ el:'#example', data:{ parentMsg:'' } })
注意:
HTML 特性是不區分大小寫的。因此,當使用的不是字符串模版,camelCased (駝峯式) 命名的 prop 須要轉換爲相對應的 kebab-case (短橫線隔開式) 命名學習
結果以下:
這樣,每當父組件的數據變化時,該變化也會傳導給子組件。ui
初學者常犯的一個錯誤是使用字面量語法傳遞數值:this
<!-- 傳遞了一個字符串 "1" --> <comp some-prop="1"></comp>
由於它是一個字面 prop,它的值是字符串 「1」 而不是 number。若是想傳遞一個實際的 number,須要使用 v-bind,從而讓它的值被看成 JavaScript 表達式計算:spa
<!-- 傳遞實際的 number --> <comp v-bind:some-prop="1"></comp>
prop 是單向綁定的:當父組件的屬性變化時,將傳導給子組件,可是不會反過來。這是爲了防止子組件無心修改了父組件的狀態——這會讓應用的數據流難以理解。
另外,每次父組件更新時,子組件的全部 prop 都會更新爲最新值。這意味着你不該該在子組件內部改變 prop。若是你這麼作了,Vue 會在控制檯給出警告。
爲何咱們會有修改 prop 中數據的衝動呢?一般是這兩種緣由:
prop 做爲初始值傳入後,子組件想把它看成局部數據來用;
prop 做爲初始值傳入,由子組件處理成其它數據輸出。
對這兩種緣由,正確的應對方式是:code
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
Vue.component('example', { props: { // 基礎類型檢測 (`null` 意思是任何類型均可以) propA: Number, // 多種類型 propB: [String, Number], // 必傳且是字符串 propC: { type: String, required: true }, // 數字,有默認值 propD: { type: Number, default: 100 }, // 數組/對象的默認值應當由一個工廠函數返回 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 自定義驗證函數 propF: { validator: function (value) { return value > 10 } } } })
type 能夠是下面原生構造器:component
咱們知道,父組件是使用 props 傳遞數據給子組件,但若是子組件要把數據傳遞回去,應該怎樣作?那就是自定義事件!orm
每一個 Vue 實例都實現了事件接口 (Events interface),即:
使用 $on(eventName) 監聽事件
使用 $emit(eventName) 觸發事件
請看下面的例子:
<div id="counter-event-example"> <p>{{total}}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter> </div>
Vue.component('button-counter',{ template:'<button v-on:click="increment">{{counter}}</button>', data:function () { return { counter : 0 } }, methods:{ increment:function () { this.counter += 1 this.$emit('increment') } } }) new Vue({ el:'#counter-event-example', data:{ total:0 }, methods:{ incrementTotal:function () { this.total += 1 } } })
運行結果以下
在本例中,子組件已經和它外部徹底解耦了。它所作的只是報告本身的內部事件,至於父組件是否關心則與它無關。留意到這一點很重要。
有時候,你可能想在某個組件的根元素上監聽一個原生事件。可使用 .native 修飾 v-on。例如:
<my-component v-on:click.native="doTheThing"></my-component>
<div id="app"> <switchbtn :result="result" @on-result-change="onResultChange"></switchbtn> <input type="button" value="change" @click="change"> </div>
Vue.component('switchbtn',{ template:"<div @click='change'>{{myResult?'開':'關'}}</div>", props:['result'], data:function () { return { myResult:this.result } }, watch:{ result : function (val) { this.myResult = val; }, myResult:function (val) { this.$emit("on-result-change", val); } }, methods:{ change:function () { this.myResult = !this.myResult; } } }) var app = new Vue({ el:'#app', data:{ result:true }, methods:{ change:function () { this.result = !this.result; }, onResultChange:function (val) { this.result = val; } } })
本文爲原創,轉載請註明出處
上一節:Vue學習筆記入門篇——組件的使用
返回目錄
下一節:Vue學習筆記入門篇——組件的內容分發(slot)