prop
HTML中的特性名是大小寫不敏感的。所以瀏覽器會把所有的大寫都解釋成小寫。這意味著當你使用dom中的模板時,amelCase (駝峰命名法) 的 prop 名需要使用其等價的 kebab-case (短橫線分隔命名) 命名:
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
如果使用的是字符串模板就不存在這個限制。
prop類型
到這里,我們只看到了,以字符串形式組成數組形式的prop。
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
但是通常你希望每個prop都有指定的類型,這時候你可以用對象的形式列出prop,這些屬性的名稱和值分別是prop各自的名稱和類型。
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object
}
這不僅為你的組件提供了文檔,還會在它們遇到錯誤的類型時從瀏覽器的 JavaScript 控制臺提示用戶。你會在這個頁面接下來的部分看到類型檢查和其它 prop 驗證。
傳遞靜態(tài)或動態(tài)的prop
傳一個靜態(tài)的prop的值
<blog-post title="My journey with Vue"></blog-post>
prop 也可以通過 v-bind 動態(tài)賦值
<!-- 動態(tài)賦予一個變量的值 -->
<blog-post v-bind:title="post.title"></blog-post>
<!-- 動態(tài)賦予一個復雜表達式的值 -->
<blog-post v-bind:title="post.title + ' by ' + post.author.name"></blog-post>
在上述兩個示例中,我們傳入的值都是字符串類型的,但實際上任何類型的值都可以傳給一個 prop。
傳入一個數字
<!-- 即便 `42` 是靜態(tài)的,我們仍然需要 `v-bind` 來告訴 Vue -->
<!-- 這是一個 JavaScript 表達式而不是一個字符串。-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 用一個變量進行動態(tài)賦值。-->
<blog-post v-bind:likes="post.likes"></blog-post>
傳入布爾值
<!-- 包含該 prop 沒有值的情況在內,都意味著 `true`。-->
<blog-post is-published></blog-post>
<!-- 即便 `false` 是靜態(tài)的,我們仍然需要 `v-bind` 來告訴 Vue -->
<!-- 這是一個 JavaScript 表達式而不是一個字符串。-->
<blog-post v-bind:is-published="false"></blog-post>
<!-- 用一個變量進行動態(tài)賦值。-->
<blog-post v-bind:is-published="post.isPublished"></blog-post>
傳入一個數組
!-- 即便數組是靜態(tài)的,我們仍然需要 `v-bind` 來告訴 Vue -->
<!-- 這是一個 JavaScript 表達式而不是一個字符串。-->
<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post>
<!-- 用一個變量進行動態(tài)賦值。-->
<blog-post v-bind:comment-ids="post.commentIds"></blog-post>
傳入一個對象
<!-- 即便對象是靜態(tài)的,我們仍然需要 `v-bind` 來告訴 Vue -->
<!-- 這是一個 JavaScript 表達式而不是一個字符串。-->
<blog-post v-bind:author="{ name: 'Veronica', company: 'Veridian Dynamics' }"></blog-post>
<!-- 用一個變量進行動態(tài)賦值。-->
<blog-post v-bind:author="post.author"></blog-post>
傳入一個對象的所有屬性
如果你想要將一個對象的所有屬性都作為 prop 傳入,你可以使用不帶參數的 v-bind (取代 v-bind:prop-name)。例如,對于一個給定的對象 post:
post: {
id: 1,
title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
等價于
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
單向數據流
所有的prop之間都是形成 單向的下行綁定。
父級的prop的更新會向下流動到子組件,但是反過來就不行。這樣式為了從子組件意外的修改父組件的內容。從而導致你的應用數據流難以理解。
另外,每次父級組件發(fā)生更新時,子組件中的值每次都會刷新為最新的值。這意味著你不應該在一個子組件中直接改變他的狀態(tài)prop。最好還是通過父級組件進行修改,這樣的一個數據流才是正確的,如果不這樣做,vue會發(fā)出警告。
這里有兩種試圖修改 prop 的情況:
1.這個prop用來傳遞一個初始的值,然后子組件中使用這個值作為他的本地數據。這樣就會用到這個prop,甚至會修改他。這時候建議定義一個data,然后將prop的值傳遞給他,用data的值判斷修改。
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
2.prop 以一種原始的值傳入,并且當這個值改變的時候需要丟視圖進行切換或者修改。這種情況下,最好使用這個prop的值來定義一個計算屬性。
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
我們接收到 size,然后計算屬性監(jiān)聽 normallizesSize,每當size發(fā)生改變的時候,會重新渲染出normallizesSize。然后視圖隨著normallizesSize的改變而改變。
注意在 JavaScript 中對象和數組是通過引用傳入的,所以對于一個數組或對象類型的 prop 來說,在子組件中改變這個對象或數組本身將會影響到父組件的狀態(tài)。
prop驗證
我們可以為 組件的props指定驗證要求。例如你知道的這些類型。如果有一個需求沒有被滿足,則 Vue 會在瀏覽器控制臺中警告你。這在開發(fā)一個會被別人用到的組件時尤其有幫助。
為了定制prop的驗證方式,你可以為 props 中的值提供一個帶有驗證需求的對象,而不是一個字符串數組。例如:
Vue.component('my-component', {
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 ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
當 prop 驗證失敗的時候,(開發(fā)環(huán)境構建版本的) Vue 將會產生一個控制臺的警告。
類型檢查
type 可以是下列原生構造函數中的一個:
StringNumberBooleanArrayObjectDateFunctionSymbol
非prop的特性
一個非prop的特性是指傳向一個組件,但是該組件并沒有相應的prop定義的的特性。
因為顯示的定義一個prop使用于向子組件傳遞一些信息。然而組件庫的作者并不總能預見組件會被用于怎樣的場景。這也是為什么組件可以接受任意的特性,而這些特性會被添加到這個組件的根元素上。