1 用法
假設父元件的模板包含子元件,我們可以通過 props 來正向地把資料從父元件傳遞給子元件。props 可以是字串陣列,也可以是物件。
html:
<div id="app">
<deniro-component message=""嫦娥四號"成功發射升空 飛向月球背面要登陸"></deniro-component>
</div>
複製程式碼
js:
Vue.component('deniro-component', {
props: ['message'],
template:
'<div>{{message}}</div>'
});
var app = new Vue({
el: '#app',
data: {}
});
複製程式碼
渲染結果:
<div id="app"><div>"嫦娥四號"成功發射升空 飛向月球背面要登陸</div></div>
複製程式碼
元件中的 props 與 data 函式的區別是:props 中的陣列來自於父級,而 data 函式是元件內定義的資料,所以它的作用域是元件本身。它們都可以在 template、computed 以及 methods 中使用。
如果需要傳遞多個資料,直接在 props 陣列中定義即可。
因為 HTML 不區分大小寫,所以當使用 DOM 模板時,建議直接使用短橫分隔(kebab-case)的命名方式來定義 props 引數名稱。
html:
<div id="app2">
<deniro-component2 special-message="微軟向谷歌投降重構Edge 但IE瀏覽器為何將長存"></deniro-component2>
</div>
複製程式碼
js:
Vue.component('deniro-component2', {
props: ['specialMessage'],
template:
'<div>{{specialMessage}}</div>'
});
var app2 = new Vue({
el: '#app2',
data: {}
});
複製程式碼
**注意:**如果使用的是字串模板,那麼可以忽略這個限制。
有時候,傳遞過來的資料來自於父級的動態資料,這是我們可以使用 v-bind
來動態繫結 props 中的資料。
html:
<div id="app3">
<input type="text" v-model="parentMessage">
<deniro-component3 :message="parentMessage"></deniro-component3>
</div>
複製程式碼
js:
Vue.component('deniro-component3', {
props: ['message'],
template:
'<div>{{message}}</div>'
});
var app3 = new Vue({
el: '#app3',
data: {
parentMessage:''
}
});
複製程式碼
效果:
這裡我們使用 v-model 繫結了父級資料 parentMessage。所以當在輸入框中鍵入的內容,也會同步傳遞給子元件。
注意:如果不使用 v-bind
來傳遞數字、布林物件、陣列或者物件,那麼傳遞的僅僅是字串!
html:
<div id="app4">
<deniro-component4 :message="['a','b','c']"></deniro-component4>
<deniro-component4 message="['a','b','c']"></deniro-component4>
</div>
複製程式碼
js:
Vue.component('deniro-component4', {
props: ['message'],
template:
'<div>引數型別:{{typeof message}};引數長度:{{message.length}}</div>'
});
var app4 = new Vue({
el: '#app4',
data: {}
});
複製程式碼
輸出結果:
引數型別:object;引數長度:3 引數型別:string;引數長度:13
2 改變單向資料流
Vue2.x 中,通過 props 傳遞的資料是單向的,也就是說,如果父元件中的資料發生變化,那麼也會影響到子元件中的資料。
有時候,因為業務場景的要求,我們需要改變這種單向資料流的設計。
2.1 作為初始值
子元件把父元件傳遞過來的值作為初始值,然後在自己的作用域內隨意修改與使用它。這可以通過在子元件的 data 內定義一個新資料,用於引用父元件中的引數。
html:
<div id="app5">
<deniro-component5 :init-value="0"></deniro-component5>
</div>
複製程式碼
js:
Vue.component('deniro-component5', {
props: ['initValue'],
template:
'<div>初始值:{{initValue}};<button @click="counter++">{{counter}}</button></div>',
data:function () {
return {
counter:this.initValue
}
}
});
var app5 = new Vue({
el: '#app5',
data: {}
});
複製程式碼
效果:
元件中定義了 counter,它被初始化為傳入的 initValue,初始化之後,counter 就與 initValue 無關啦O(∩_∩)O~
2.2 轉換後傳入
有時候,我們必須把 props 中的值轉換後傳入子元件,這可以通過計算屬性來實現。
html:
<div id="app6">
<deniro-component6 :border="5" :width="200"></deniro-component6>
</div>
複製程式碼
js:
Vue.component('deniro-component6', {
props: ['border', 'width'],
template:
'<div :style="style">一個演算法通吃三大棋類</div>',
computed: {
style: function () {
return {
border: this.border + 'px solid red',
width: this.width + 'px'
}
}
}
});
var app6 = new Vue({
el: '#app6',
data: {}
});
複製程式碼
效果:
**注意:**在 JS 中,物件與陣列是引用型別,即子元件中定義的變數如果賦值的是這些型別,那麼改變這些變數的值,是會影響到父元件的!
3 驗證
我們自定義的元件,如果需要提供給第三方使用,那麼最好進行引數驗證,這就需要用到物件寫法。如果驗證失敗,那麼會在瀏覽器的控制檯輸出警告日誌。
html:
<div id="app7">
<deniro-component7 :a="'str'"></deniro-component7>
</div>
複製程式碼
js:
<script src="https://cdn.bootcss.com/vue/2.2.2/vue.js"></script>
<script>
Vue.component('deniro-component7',{
props:{
a:Number
},
template:
'<div >{{a}}</div>',
});
var app7 = new Vue({
el: '#app7',
data: {}
});
</script>
複製程式碼
**注意:**這裡引入了開發版的 vue.js(生產版一般是 vue.min.js)。
控制檯輸出:
其它示例:
Vue.component('deniro-component8', {
props: {
//必須是數字型別
a: Number,
//數字型別或者字串型別
b: [Number, String],
//布林型別,預設值為 true
c: {
type: Boolean,
default: true
},
//字串型別,必須傳值
d: {
type: String,
required: true
},
//自定義
e: {
validator: function (v) {
return v > 1;
}
}
}
});
複製程式碼
type 可以為這些型別:String、Number、Boolean、Object、Array、Function。
以上示例 DEMO