props 類型
爲何須要 props 類型呢?就好比咱們子組件須要用到父組件的數據,咱們到底該使用何種方式傳遞進去呢?咱們都知道在原生 DOM 中有一種 data- 屬性,能夠將數據綁定,因此相似這種方式,props 就應運而生了。vue
咱們仍是接着上節課的例子,在 src/views/TestCom.vue
,接收父組件傳遞進來的屬性 title
:web
<template>
<div class="test-com-wrap">{{title}}</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
},
};
</script>
而後咱們在 src/views/TemplateM.vue
來使用 TestCom
組件,向 TestCom
組件傳遞 title
屬性:數組
<template>t
<div class="template-m-wrap">
<test-com title="這個是組件"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
};
},
};
</script>
咱們訪問 http://localhost:8080/template_m
瀏覽實際效果以下:瀏覽器
傳遞靜態或動態 Prop
從上面咱們知道咱們直接像下面這段代碼,就是咱們所說的靜態屬性:微信
<test-com title="這是組件"></test-com>
若是咱們把這個 title
屬性綁定一個變量,那就是動態綁定屬性:app
<template>t
<div class="template-m-wrap">
<test-com :title="searchText"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "這個是組件",
};
},
};
</script>
效果仍是跟上面同樣:編輯器
傳入一個數字
假如子組件須要接收父組件的一個數值,那麼咱們能夠給 props
傳遞一個數字類型,接下來咱們在 src/views/TestCom.vue
來添加一個數字類型的 props
:函數
<template>
<div class="test-com-wrap">{{title}}-{{num}}</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0
}
},
};
</script>
在 src/views/TemplateM.vue
來傳遞一個數字:post
<template>
<div class="template-m-wrap">
<test-com title="這個是組件" :num="42"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
};
},
};
</script>
咱們來看看效果如何:flex
傳入一個布爾值
咱們一樣在 src/views/TestCom.vue
設置一個布爾類型的 props:
<template>
<div class="test-com-wrap">{{title}}-{{num}}-{{bool}}</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0
},
bool: {
type: Boolean,
default: false
}
},
};
</script>
在 src/views/TemplateM.vue
來使用:
<template>
<div class="template-m-wrap">
<test-com title="這個是組件" :num="42" :bool="true"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
};
},
};
</script>
最後咱們來查看下效果:
傳入一個數組
咱們一樣在 src/views/TestCom.vue
接收一個數組類型的 props:
<template>
<div class="test-com-wrap">
{{ title }}-{{ num }}-{{ bool }}
<ul v-if="arr.length">
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0,
},
bool: {
type: Boolean,
default: false,
},
arr: {
type: Array,
default: () => ([]),
},
},
};
</script>
在 src/views/TemplateM.vue
來使用:
<template>
<div class="template-m-wrap">
<test-com title="這個是組件" :num="42" :bool="true" :arr="arr"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
arr: ['code', 'Ken', '理財投資']
};
},
};
</script>
來看看效果以下:
傳入一個對象
咱們一樣在 src/views/TestCom.vue
接收一個 Object 類型的 props:
<template>
<div class="test-com-wrap">
{{ title }}-{{ num }}-{{ bool }}
<ul v-if="arr.length">
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
</ul>
{{obj.name}}
</div>
</template>
<script>
export default {
name: "TestCom",
props: {
title: {
type: String,
default: "",
},
num: {
type: Number,
default: 0,
},
bool: {
type: Boolean,
default: false,
},
arr: {
type: Array,
default: () => ([]),
},
obj: {
type: Object,
default: () => ({})
}
},
};
</script>
在 src/views/TemplateM.vue
使用:
<template>
<div class="template-m-wrap">
<test-com title="這個是組件" :num="42" :bool="true" :arr="arr" :obj="obj"></test-com>
</div>
</template>
<script>
import TestCom from './TestCom'
export default {
name: "TemplateM",
components: {
TestCom
},
data() {
return {
searchText: "",
arr: ['code', 'Ken', '理財投資'],
obj: {
name: "Ken"
}
};
},
};
</script>
來看看效果以下:
傳入一個對象的全部 property
若是你想要將一個對象的全部 property 都做爲 prop 傳入,你可使用不帶參數的 v-bind
(取代 v-bind
:prop-name
)。例如,對於一個給定的對象 post
:
post: {
id: 1,
title: 'My Journey with Vue'
}
下面的模板:
<test-com v-bind="post"></test-com>
等價於:
<test-com v-bind:id="post.id" v-bind:title="post.title"></test-com>
單向數據流
全部的 prop 都使得其父子 prop 之間造成了一個「單向下行綁定」:父級 prop 的更新會向下流動到子組件中,可是反過來則不行。這樣會防止從子組件意外變動父級組件的狀態,從而致使你的應用的數據流向難以理解。
另外,每次父級組件發生變動時,子組件中全部的 prop 都將會刷新爲最新的值。這意味着你「不」應該在一個子組件內部改變 prop。若是你這樣作了,Vue 會在瀏覽器的控制檯中發出警告。
這裏有兩種常見的試圖變動一個 prop 的情形:
-
這個 「prop 用來傳遞一個初始值;這個子組件接下來但願將其做爲一個本地的 prop 數據來使用」。在這種狀況下,最好定義一個本地的 data property 並將這個 prop 用做其初始值
props: ['initialCounter'],
data() {
return {
counter: this.initialCounter
}
}
-
這個 prop 以一種原始的值傳入且須要進行轉換**。在這種狀況下,最好使用這個 prop 的值來定義一個計算屬性
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
Prop 驗證
咱們能夠爲組件的 prop 指定驗證要求,例如你知道的這些類型。若是有一個需求沒有被知足,則 Vue 會在瀏覽器控制檯中警告你。這在開發一個會被別人用到的組件時尤爲有幫助。
爲了定製 prop 的驗證方式,你能夠爲 props
中的值提供一個帶有驗證需求的對象,而不是一個字符串數組。例如:
app.component('my-component', {
props: {
// 基礎的類型檢查 (`null` 和 `undefined` 會經過任何類型驗證)
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
}
},
// 具備默認值的函數
propG: {
type: Function,
// 與對象或數組默認值不一樣,這不是一個工廠函數 —— 這是一個用做默認值的函數
default: function() {
return 'Default function'
}
}
}
})
類型檢查
type
能夠是下列原生構造函數中的一個:
-
String -
Number -
Boolean -
Array -
Object -
Date -
Function -
Symbol
Prop 的大小寫 (camelCase vs kebab-case)
HTML 中的 attribute 名是大小寫不敏感的,因此瀏覽器會把全部大寫字符解釋爲小寫字符。這意味着當你使用 DOM 中的模板時,camelCase (駝峯命名法) 的 prop 名須要使用其等價的 kebab-case (短橫線分隔命名) 命名:
const app = Vue.createApp({})
app.component('blog-post', {
// camelCase in JavaScript
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
使用以下:
<blog-post post-title="hello!"></blog-post>
重申一次,若是你使用字符串模板,那麼這個限制就不存在了。
本文分享自微信公衆號 - 人生代碼(lijinwen1996329ken)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。