上篇component
元件有說到每個元件範圍都應該是獨立的,更不應該發生子元件直接改變根元件的情況,元件與元件又該怎麼正確傳遞資料呢?
Props
起手式子元件做好之後,為了能重複使用,就會使用外部元件的資料,供傳子元件使用,但是又不能靠子元件直接取用,這時就用使用props
屬性來完成。
<div id="app">
<h4>{{ text }}</h4>
<con-tainer :test-props="demo"></con-tainer>
</div>
:test-props="demo"
,前面的:test-props
是內層元件
,後面的"demo"
是外層元件
,好記的方式:前內後外。
const app = Vue.createApp({
data() {
return {
text: "外部元件",
demo: "外部元件傳遞的文字"
};
}
});
app.component("ConTainer", {
props: ["testProps"],
template: `<div>
<h4>{{ text }}</h4><h3>{{ testProps }}<h3>
</div>`
});
app.mount("#app");
內部元件的props
屬性宣告從外部引入到內部元件,並且透過外層模板的v-bind
完成兩個元件的資料傳遞,HTML
可以說是兩個元件溝通的橋樑。
補充:``props
命名有使用駝峰命名,記得寫在模板時要改為連字號,因為HTML
不分大小寫,例如:props: ["testProps"]
的testProps
要改為test-props
。
props
單向數據流當內層元件想使用v-model
來改變外層元件的資料時會跳出這行警告,[Vue warn]: Attempting to mutate prop "test". Props are readonly.
,Props
是有讀取限制的。
<div id="app">
<con-tainer :test-props="demo"></con-tainer>
</div>
const app = Vue.createApp({
data() {
return {
demo: "外部元件傳遞的文字"
};
}
});
app.component("ConTainer", {
props: ["testProps"],
template: `<div>
<h3>{{ testProps }}<h3>
<input type="text" v-model="testProps">
</div>`
});
app.mount("#app");
props
時有v-bind
與沒有v-bind
的區別觀察import-num
有無綁定v-bind
的差別:
<div id="app">
<con-tainer import-num="400"></con-tainer>
<con-tainer :import-num="num"></con-tainer>
</div>
const app = Vue.createApp({
data() {
return {
num: 500
};
}
});
app.component("ConTainer", {
props: ["importNum"],
template: `<div>
<h3>value: {{ importNum }} </h3>
<h3>value: {{ typeof importNum }} </h3>
</div>`
});
app.mount("#app");
在外部元件的模板裡,未綁定v-bind
的情況下,內部元件props
依然可以接受資料,任何值傳入到內部元件props
都會是string
的型別。有綁定v-bind
就會依據外部元件data
的num
型別,內部也會顯示該型別。
props
型別驗證多人開發有時會需要驗證外部元件props
傳入的型別,這時就可以使用型別驗證的技巧,來得知適當的提示。
上面範例在內元件中props
都是使用陣列方式(可以帶多個值),例如props:['one','two']
,如果要進行驗證,就要改為大括號物件的形式。
準備好一個內部元件areaComponent
,console.log
還不會跳出提示:
<div id="app">
<area-component
:pro-a="fun" :pro-b="text"
pro-c="num" :pro-d="num">
</area-component>
</div>
const areaComponent = {
props: {
proA: Function,
//多個型別檢查
proB: [String, Number],
//必要值 物件形式可以設立多個條件
proC: {
type: String,
required: true
},
//預設值
proD: {
type: Number,
default: "hello"
}
},
template: `{{ proA }} <br> {{ proB }} <br> {{ proC }} <br> {{ proD }}`
};
const app = Vue.createApp({
data() {
return {
num: 500,
text: "小明",
boo: true,
fun: () => {
return "a";
},
test: 100
};
},
components: {
areaComponent
}
});
app.mount("#app");
將上面範例程式碼內部元件:pro-a="fun"
的fun
改為text
:
<div id="app">
<area-component :pro-a="text" :pro-b="text" pro-c="num" :pro-d="num"></area-component>
</div>
此時console.log
就會跳出提示:[Vue warn]: Invalid prop: type check failed for prop 'proA'. Expected Function, got String with value '小明'.
意思是預期應該是一個Function
,但傳入結果卻是字串
。
required: true
:一定要給一個值,如果沒有就會跳出提示。default: "hello"
:當沒有透過props
傳入值,畫面就會給出hello
的預設值,可以將:pro-d="num"
移除看出差異在哪裡。pro-c="num"
:console.log
為什麼沒跳出提示?因為沒綁定v-bind
,都會自動變成String
型別。
以上如有錯誤,歡迎指教