組件的分類
- 全局組件 : 可以聲明一次在任何地方使用(一般寫插件的時(shí)候全局使用的多一點(diǎn))
- 局部組件: 必須告訴這個(gè)組件屬于誰(shuí)(一般用局部比較好)
props是只讀的,vue底層會(huì)檢測(cè)你對(duì)props的修改,如果進(jìn)行了修改,控制臺(tái)會(huì)報(bào)錯(cuò),必須修改,就復(fù)制一份到data中,通過(guò)data去修改數(shù)據(jù)。
我們?cè)赿ata里面重新定義一個(gè)變量去接收props屬性。這個(gè)變量最好不要重名,重名的話,優(yōu)先獲取props屬性值,優(yōu)先級(jí)props>data。
全局組件(component)
全局注冊(cè)的組件可以在隨后創(chuàng)建的 app 實(shí)例模板中使用,也包括根實(shí)例組件樹(shù)中的所有子組件的模板中
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<runoob></runoob>
<!-- 組件間數(shù)據(jù)相互獨(dú)立 -->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
// 創(chuàng)建一個(gè)Vue 應(yīng)用
const app = Vue.createApp({})
// 定義一個(gè)名為 runoob的新全局組件
app.component('runoob', {
template: '<h1>自定義組件!</h1>'
})
// 定義一個(gè)名為 button-counter的新全局組件
app.component('button-counter', {
data() {
return {
count: 0
}
},
template: `
<button @click="count++">
點(diǎn)了 {{ count }} 次!
</button>`
})
app.component('runoob', {
template: '<h1>自定義組件!</h1>'
})
app.mount('#app')
</script>
瀏覽器渲染
局部組件(components)
//對(duì)象
const ComponentA = {
/* ... */
}
const ComponentB = {
/* ... */
}
//使用
const app = Vue.createApp({
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
對(duì)于 components 對(duì)象中的每個(gè)屬性來(lái)說(shuō),其屬性名就是自定義元素的名字(component-a、component-b),其屬性值就是這個(gè)組件的選項(xiàng)對(duì)象(ComponentA、ComponentB)。
我們也可以在實(shí)例選項(xiàng)中注冊(cè)局部組件,這樣組件只能在這個(gè)實(shí)例中使用:
定義兩個(gè)局部組件
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<runoob-a></runoob-a>
<runoob-b></runoob-b>
</div>
<script>
var runoobA = {
template: '<h1>自定義組件A!</h1>'
}
var runoobB = {
template: '<h1>自定義組件B!</h1>'
}
const app = Vue.createApp({
components: {
'runoob-a': runoobA,
'runoob-b': runoobB,
}
})
app.mount('#app')
</script>
瀏覽器渲染結(jié)果:
Prop
prop 是子組件用來(lái)接受父組件傳遞過(guò)來(lái)的數(shù)據(jù)的一個(gè)自定義屬性。
父組件的數(shù)據(jù)需要通過(guò) props 把數(shù)據(jù)傳給子組件,子組件需要顯式地用 props 選項(xiàng)聲明 “prop”:
一個(gè)組件默認(rèn)可以擁有任意數(shù)量的 prop,任何值都可以傳遞給任何 prop。
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<site-name name="Muze" mail="1@1.com"></site-name>
</div>
<script>
const app = Vue.createApp({})
app.component('site-name', {
props: ['name', 'mail'],
template: `<h2>昵稱:{{ name }}<br />郵箱:{{ mail }}</h2>`
})
app.mount('#app')
</script>
瀏覽器渲染結(jié)果
動(dòng)態(tài) Prop
類似于用 v-bind 綁定 HTML 特性到一個(gè)表達(dá)式,也可以用 v-bind 動(dòng)態(tài)綁定 props 的值到父組件的數(shù)據(jù)中。每當(dāng)父組件的數(shù)據(jù)變化時(shí),該變化也會(huì)傳導(dǎo)給子組件:
<div id="app">
<site-info v-for="site in sites" :id="site.id" :title="site.title"></site-info>
</div>
<script>
const Site = {
data() {
return {
sites: [
{ id: 1, title: 'Google' },
{ id: 2, title: 'Runoob' },
{ id: 3, title: 'Taobao' }
]
}
}
}
const app = Vue.createApp(Site)
app.component('site-info', {
props: ['id', 'title'],
template: `<h4>{{ id }} - {{ title }}</h4>`
})
app.mount('#app')
</script>
瀏覽器演示效果
限制
- 類型屬性:type:xx
- 必傳屬性:required:true
- 默認(rèn)屬性:default:xx
Prop 驗(yàn)證
組件可以為 props 指定驗(yàn)證要求。
為了定制 prop 的驗(yàn)證方式,你可以為 props 中的值提供一個(gè)帶有驗(yàn)證需求的對(duì)象,而不是一個(gè)字符串?dāng)?shù)組。例如:
Vue.component('my-component', {
props: {
// 基礎(chǔ)的類型檢查 (`null` 和 `undefined` 會(huì)通過(guò)任何類型驗(yàn)證)
propA: Number,
// 多個(gè)可能的類型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 帶有默認(rèn)值的數(shù)字
propD: {
type: Number,
default: 100
},
// 帶有默認(rèn)值的對(duì)象
propE: {
type: Object,
// 對(duì)象或數(shù)組默認(rèn)值必須從一個(gè)工廠函數(shù)獲取
default: function () {
return { message: 'hello' }
}
},
// 自定義驗(yàn)證函數(shù)
propF: {
validator: function (value) {
// 這個(gè)值必須匹配下列字符串中的一個(gè)
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
當(dāng) prop 驗(yàn)證失敗的時(shí)候,(開(kāi)發(fā)環(huán)境構(gòu)建版本的) Vue 將會(huì)產(chǎn)生一個(gè)控制臺(tái)的警告。
type 可以是下面原生構(gòu)造器:
StringNumberBooleanArrayObjectDateFunctionSymbol
type 也可以是一個(gè)自定義構(gòu)造器,使用 instanceof 檢測(cè)。
例子
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<site-name name="Muze" mail="1@1.com" age="18"></site-name>
</div>
<script>
const app = Vue.createApp({})
app.component('site-name', {
props: {
//昵稱
"name": {
type: String, //類型屬性
required: true, //必傳屬性
default: "外星人", //默認(rèn)值
},
//郵箱
"mail": {
type: String,
required: false,
default: "myemail@email.com",
},
//年齡
"age": {
type: Number,
required: true,
default: "未知",
}
},
template: `<h2>
昵稱:{{ name }}<br />
郵箱:{{ mail }}<br />
年齡:{{ age }}</h2>`
})
app.mount('#app')
</script>
瀏覽器渲染
組件接收外部傳來(lái)數(shù)據(jù)的三種方式:
(1)只接收:props: [‘name’,’age’,’sex’]
(2)接收并限制類型:props: { “name”:Number }
(3)限制類型、限制必要性指定默認(rèn)值:
props:{
"name":{
type:String,
required:true
},
"age":{
type:Number,
default:18
},
"sex":{
type:String,
default:'男'
},
},
年齡+1歲
<site-name name="Muze" mail="1@1.com" :age="18"></site-name>
年齡:{{ age+1 }}</h2>
做個(gè)按鈕,年齡點(diǎn)擊變99歲
待完善
實(shí)戰(zhàn)代碼
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
<h1>{{ msg }}</h1>
<button @click="add">計(jì)數(shù)器:{{counte}}</button>
<site-name></site-name>
</div>
<script>
//父組件
const appRoot = {
data() {
return {
msg: "個(gè)人基本信息",
counte: 1,
}
},
methods: {
add() {
this.counte += 1;
}
},
}
app = Vue.createApp(appRoot);
//子組件
app.component('site-name', {
props: {
//年齡
"age": {
type: Number,
required: true,
default: "18",
}
},
template: `<h2>年齡:{{ age }}</h2>`,
})
app.mount('#app');
</script>
瀏覽器渲染
