vue學習十一(prop傳不同值、 v-bind 動態賦值、單向資料流、prop校驗)
區域性註冊
在這些情況下,你可以通過一個普通的 JavaScript 物件來定義元件:
var ComponentA = { /* ... */ }
然後在 components 選項中定義你想要使用的元件:
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
對於 components 物件中的每個屬性來說,其屬性名就是自定義元素的名字,其屬性值就是這個元件的選項物件
我們看下面的例子:
<div id="div2"> <my-component> </my-component> </div> <script type="text/javascript"> var Child = { template: '<div>A custom component!</div>' } new Vue({ el: "#div2", components: { 'my-component': Child } }) </script>
dom模板解析注意事項
有些 HTML 元素,諸如 <ul>、<ol>、<table> 和 <select>
,對於哪些元素可以出現在其內部是有嚴格限制的。而有些元素,諸如 <li>、<tr> 和 <option>
,只能出現在其它某些特定的元素內部。
這會導致我們使用這些有約束條件的元素時遇到一些問題。例如:
<table>
<blog-post-row></blog-post-row>
</table>
這個自定義元件 會被作為無效的內容提升到外部,並導致最終渲染結果出錯。幸好這個特殊的 is 特性給了我們一個變通的辦法:
<table>
<tr is="blog-post-row"></tr>
</table>
我們看一個例子如下:
<ul id="ul1"> <li is="my-li"></li> </ul> <script type="text/javascript"> var Child = { template: '<li>xx!</li>' } new Vue({ el: "#ul1", components: { 'my-li': Child } }) </script>
用 Prop 傳遞不同值型別
以前只看到了以字串陣列形式列出的 prop 但是,通常你希望每個 prop 都有指定的值型別。這時,你可以以物件形式列出 prop,這些屬性的名稱和值分別是 prop 各自的名稱和型別
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object
}
我們看下面這個例子:
<child id="div1" message="hello!"></child>
<script type="text/javascript">
Vue.component('child', {
props: {'message':String},
template: '<span>{{ message }}</span>'
})
new Vue({
el: "#div1",
})
</script>
效果輸出如下:
hello!
用 Prop通過 v-bind 動態賦值
<div id="div2">
<input type="text" v-model="parentMsg">
<component1 v-bind:msg="parentMsg"></component1>
</div>
<script type="text/javascript">
Vue.component("component1", {
props: ["msg"],
template: "<span>{{msg}}</span>"
})
new Vue({
el: "#div2",
data: {
parentMsg: "父元件初始化資料"
}
})
</script>
效果圖如下:
父元件初始化資料 父元件初始化資料
用 Prop傳遞物件的所有屬性
方式一我們可以使用v-bind:prop-name進行物件屬性的傳遞
<div id="div3">
<todo-item v-bind:text="todo.text" v-bind:complete="todo.isComplete"></todo-item>
</div>
<script type="text/javascript">
Vue.component("todo-item", {
props: ["text", "complete"],
template: "<span>{{text}}{{complete}}</span>"
})
new Vue({
el: "#div3",
data: {
todo: {
text: 'Learn',
isComplete: "Vue"
}
}
})
</script>
方式二我們可以使用不帶引數的 v-bind
<div id="div4">
<todo-item v-for="item in todo" v-bind:todo="item"></todo-item>
</div>
<script type="text/javascript">
Vue.component("todo-item", {
props: ["todo"],
template: "<span>{{todo}}</span>"
})
new Vue({
el: "#div4",
data: {
todo: {
text: 'Learn',
isComplete: "Vue"
}
}
})
</script>
輸出效果如下:
LearnVue
用 Prop傳遞物件陣列
<div id="div5">
<todo-item v-for="item in todo" v-bind:todo="item"></todo-item>
</div>
<script type="text/javascript">
Vue.component("todo-item", {
props: ["todo"],
template: "<span>{{todo.text}},{{todo.isComplete}}</span>"
})
new Vue({
el: "#div5",
data: {
todo: [{
text: 'Learn',
isComplete: "Vue"
}, {
text: 'yes',
isComplete: "no"
}]
}
})
</script>
輸出效果如下:
Learn,Vueyes,no
用 Prop傳入一個數字
<div id="div6">
<comp todo="1+23"></comp>
<!-- 這裡用了動態語法,傳遞的值會通過js的表示式計算,傳遞的是數字 -->
<comp v-bind:todo="1+23"></comp>
</div>
<script type="text/javascript">
Vue.component("comp", {
props: ["todo"],
template: "<span>{{todo}}</span>"
})
new Vue({
el: "#div6",
})
</script>
輸出如下:
1+23 24
單向資料流
所有的 prop 都使得其父子 prop 之間形成了一個單向下行繫結:父級 prop 的更新會向下流動到子元件中,但是反過來則不行。這樣會防止從子元件意外改變父級元件的狀態,從而導致你的應用的資料流向難以理解。
額外的,每次父級元件發生更新時,子元件中所有的 prop 都將會重新整理為最新的值。這意味著你不應該在一個子元件內部改變 prop。如果你這樣做了,Vue 會在瀏覽器的控制檯中發出警告。
這裡有兩種常見的試圖改變一個 prop 的情形:
1、這個 prop 用來傳遞一個初始值;這個子元件接下來希望將其作為一個本地的 prop 資料來使用。在這種情況下,最好定義一個本地的 data 屬性並將這個 prop 用作其初始值
:
<div id="div7">
<input type='text' v-model="msg">
<child v-bind:message='msg'></child>
</div>
<script type="text/javascript">
var tmp = 0;
Vue.component('child', {
props: ['message'],
template: '<p>message:{{ message}} --tmp:{{tmp}}</p>',
data: function () {
return { tmp: this.message }
},
})
new Vue({
el: '#div7',
data: {
msg: '我是msg'
}
})
</script>
效果圖如下:
2、這個 prop 以一種原始的值傳入且需要進行轉換。在這種情況下,最好使用這個 prop 的值來定義一個計算屬性
<div id="div8">
<input type='text' v-model="msg">
<child v-bind:message='msg'></child>
</div>
<script type="text/javascript">
Vue.component('child', {
props: ['message'],
template: '<p>message:{{ normalizedSize}} </p>',
computed: {
normalizedSize: function () {
return this.message += "_str"
}
}
})
new Vue({
el: '#div8',
data: {
msg: '我是msg'
}
})
</script>
Prop 驗證
我們可以為元件的 prop 指定驗證要求,例如你知道的這些型別。如果有一個需求沒有被滿足,則 Vue 會在瀏覽器控制檯中警告你
為了定製 prop 的驗證方式,你可以為 props 中的值提供一個帶有驗證需求的物件,而不是一個字串陣列。例如:
<div id="app">
<my-child :num="100" :msg="'sdf'" :object="{a:'a'}" :cust="100">
</child>
</div>
<script type="text/javascript">
Vue.component('my-child', {
props: {
// 基礎型別檢測 (`null` 意思是任何型別都可以)
num: Number,
// 多種型別
propB: [String, Number],
// 必傳且是字串
msg: {
type: String,
required: true
},
// 數字,有預設值
num1: {
type: Number,
default: 1000
},
// 陣列/物件的預設值應當由一個工廠函式返回
object: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定義驗證函式
cust: {
validator: function (value) {
return value > 10
}
}
},
template: `<div>
<p>{{ num }}</p>
<p>{{ msg }}</p>
<p>{{ num1 }}</p>
<p>{{ object }}</p>
<p>{{ cust }}</p>
</div>`
})
new Vue({
el: "#app"
});
</script>
效果輸出如下:
100
sdf
1000
{ "a": "a" }
100