在 Vue 中,父子組件的關係可以總結為 props向下傳遞,事件向上傳遞。父組件通過 props 給子組件下發數據,子組件通過事件給父組件發送消息。看看它們是怎麼工作的。 一、基本用法 組件不僅僅是要把模板的內容進行復用,更重要的是組件間要進行通信。 在組件中,使用選項props 來聲明需要從父級 ...
在 Vue 中,父子組件的關係可以總結為 props向下傳遞,事件向上傳遞。父組件通過 props 給子組件下發數據,子組件通過事件給父組件發送消息。看看它們是怎麼工作的。
一、基本用法
組件不僅僅是要把模板的內容進行復用,更重要的是組件間要進行通信。
在組件中,使用選項props 來聲明需要從父級接收的數據, props 的值可以是兩種, 一種是字元串數組,一種是對象。
1.1 字元串數組:
<div id="app4"> <my-component4 message="數據來自父組件"></my-component4> </div>
Vue.component('my-component4',{ props: ['message'], template: '<div>{{message}}</div>' }); var app4 = new Vue({ el: '#app4' });
渲染後的結果為: <div id= ” app4”> <div >來自父組件的數據</ div> </div>
props 中聲明的數據與組件data 函數return 的數據主要區別就是props 的來自父級,而data 中的是組件自己的數據,作用域是組件本身,這兩種數據都可以在模板template 及計算屬性computed和方法methods 中使用。
上例的數據message 就是通過props 從父級傳遞過來的,在組件的自定義標簽上直接寫該props 的名稱,如果要傳遞多個數據,在props 數組中添加項即可。
有時候,傳遞的數據並不是直接寫死的,而是來自父級的動態數據,這時可以使用指令v -bind來動態綁定props 的值,當父組件的數據變化時,也會傳遞給子組件。
<div id="app5"> <input type="text" v-model="text"> <my-component5 :my-text="text"></my-component5> </div>
Vue.component('my-component5',{ props: ['myText'], template: '<div>{{myText}}</div>' }); var app5 = new Vue({ el: '#app5', data: { text: '動態傳遞父組件數據' } });
註意的幾個點:
1.如果你要直接傳遞數字、布爾值、數組、對象,而且不使用v-bind ,傳遞的僅僅是字元串。
2.如果你想把一個對象的所有屬性作為 prop 進行傳遞,可以使用不帶任何參數的 v-bind
(即用 v-bind
而不是 v-bind:prop-name
)。例如,已知一個 todo
對象:
1.2 對象:
當prop 需要驗證時,就需要對象寫法。
一般當你的組件需要提供給別人使用時,推薦都進行數據驗證,比如某個數據必須是數字類型,如果傳入字元串,就會在控制台彈出警告。
<div id="app6"> <input type="text" v-model="number"> <my-component6 :my-text="number"></my-component6> </div>
Vue.component('my-component6',{ props: { 'myText':{ type: Number, //必須是數字類型的 required: true, //必須傳值 default: 1 //如果未定義,預設值就是1 } }, template: '<div>{{myText}}</div>' }); var app6 = new Vue({ el: '#app6', data: { number: 1 } });
驗證的type 類型可以是:
• String
• Number
• Boolean
• Object
• Array
• Function
type 也可以是一個自定義構造器,使用instanceof 檢測。
當prop 驗證失敗時,在開發版本下會在控制台拋出一條警告。
二、單向數據流
Vue 2.x 與Vue l.x 比較大的一個改變就是, Vue2.x 通過props 傳遞數據是單向的了, 也就是父組件數據變化時會傳遞給子組件,但是反過來不行。
業務中會經常遇到兩種需要改變prop 的情況,
2.1 一種是父組件傳遞初始值進來,子組件將它作為初始值保存起來,在自己的作用域下可以隨意使用和修改。(Prop 作為初始值傳入後,子組件想把它當作局部數據來用;)
這種情況可以在組件data 內再聲明一個數據,引用父組件的prop ,示例代碼如下:
<div id="app7"> <my-component7 :init-count="1"></my-component7> </div>
Vue.component('my-component7',{ props: ['initCount'], template: '<div>{{count}}</div>', data: function(){ return { count: this.initCount } } }); var app7 = new Vue({ el: '#app7' });
組件中聲明瞭數據count , 它在組件初始化時會獲取來自父組件的initCount , 之後就與之無關了,只用維護c ount , 這樣就可以避免直接操作initCount 。
2.2 prop 作為需要被轉變的原始值傳入。(Prop 作為原始數據傳入,由子組件處理成其它數據輸出。)
這種情況用計算屬性就可以了, 示例代碼如下:
<div id="app8"> <my-component8 :width="100"></my-component8> </div>
Vue.component('my-component8',{ props: ['width'], template: '<div :style="style">組件內容</div>', computed: { style: function(){ return { width: this.width+'px' } } } }); var app8 = new Vue({ el: '#app8' });
註意在 JavaScript 中對象和數組是引用類型,指向同一個記憶體空間,如果 prop 是一個對象或數組,在子組件內部改變它會影響父組件的狀態。