創(chuàng)鍵組件
兩種方式:
方法一:使用Vue.extend({})
var component = Vue.extend({
template: '<div>component</div>'
});
// 里面還可以添加其他的屬性
方法二:使用字面量
var component = {
template: '<div>component</div>'
}
注冊(cè)組件
全局注冊(cè)
語法:
Vue.component('my-component', {
// 選項(xiàng)
})
示例:
// 創(chuàng)建組件
var component = {template: '<div>component</div>'}
// 全局注冊(cè)組件
Vue.component('my-component', component);
局部注冊(cè)
// 創(chuàng)建組件
var component = {template: '<div>component</div>'}
// 在 Vue組件實(shí)例內(nèi)注冊(cè)component組件,該組件只能在該實(shí)例中使用
var vm = new Vue({
el: '#app',
components: {
'mycomponent ': component ,
}
})
注意點(diǎn):
- HTML 特性是不區(qū)分大小寫的。所以笛质,當(dāng)使用的不是字符串模版陆错,camelCased (駝峰式) 命名的 prop 需要轉(zhuǎn)換為相對(duì)應(yīng)的 kebab-case (短橫線隔開式) 命名:
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'], // 這里使用的是駝峰式命名
template: '<span>{{ myMessage }}</span>'
})
// 在下面的HTML文件中引用時(shí),需要改為kebab-case的形式剪侮,也就是短橫線隔開
<child my-message="hello!"></child>
如果你使用字符串模版汤善,則沒有這些限制。
注意(謹(jǐn)記):在HTML中票彪,屬性是不區(qū)分大小寫的红淡,例如:class、Class或CLASS都是表示class降铸,因此在旱,當(dāng)在Vue中使用props向子組件傳遞數(shù)據(jù)時(shí),如果props是駝峰式命名推掸,那么在HTML文件中使用時(shí)桶蝎,需要修改為kebab-case(短橫線隔開式或稱為烤肉串)的形式,否則谅畅,Vue將會(huì)無法解析
使用props傳遞數(shù)據(jù)
Vue.component('child', {
// 聲明 props
props: ['message'],
// 就像 data 一樣登渣,prop 可以用在模板內(nèi)
// 同樣也可以在 vm 實(shí)例中像“this.message”這樣使用
template: '<span>{{ message }}</span>'
})
// 通過下面這種方式傳遞數(shù)據(jù)
<child message="hello!"></child>
動(dòng)態(tài)prop
將父組件的數(shù)據(jù)通過v-bind
綁定到子組件上,與綁定HTML特性是一樣的毡泻;每當(dāng)父組件的數(shù)據(jù)變化都會(huì)反映到子組件上
<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>
字面量語法 VS 動(dòng)態(tài)語法
初學(xué)者常犯的一個(gè)錯(cuò)誤是使用字面量語法傳遞數(shù)值:
<!-- 傳遞了一個(gè)字符串 "1" -->
<comp some-prop="1"></comp>
因?yàn)樗且粋€(gè)字面 prop胜茧,它的值是字符串 "1" 而不是 number。如果想傳遞一個(gè)實(shí)際的 number仇味,需要使用 v-bind呻顽,從而讓它的值被當(dāng)作 JavaScript 表達(dá)式計(jì)算:
<!-- 傳遞實(shí)際的 number -->
<comp v-bind:some-prop="1"></comp>
通過v-bind:some-props="1"
傳遞的是一個(gè)number,而通過some-prop="1"
傳遞的是一個(gè) 字符串
props數(shù)據(jù)校驗(yàn)
Vue.component("example", {
props: {
// 基礎(chǔ)類型檢測(cè) (`null` 意思是任何類型都可以)
propA: Number,
// 多種類型
propB: [String, Number],
// 必傳且是字符串
propC: {
type: String,
required: true
},
// 數(shù)字丹墨,有默認(rèn)值
propD: {
type: Number,
default: 100
},
// 數(shù)組/對(duì)象的默認(rèn)值應(yīng)當(dāng)由一個(gè)工廠函數(shù)返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定義驗(yàn)證函數(shù)
propF: {
validator: function (value) {
return value > 10
}
}
}
});
注意:props會(huì)在組件實(shí)例創(chuàng)建之前進(jìn)行校驗(yàn)廊遍,所以在default、validator函數(shù)里贩挣,諸如:data
, computed
或methods
等實(shí)例屬性都無法使用
非props特性傳遞
在Vue中喉前,在大多數(shù)情況下,傳遞給組件的值會(huì)覆蓋組件本身就設(shè)定的值王财,例如傳遞type=large
會(huì)覆蓋組件上的type=small
卵迂,且有可能破壞該組件,但是搪搏,對(duì)于class和style特性在傳遞時(shí)狭握,不會(huì)發(fā)生覆蓋,只會(huì)合并疯溺,假如組件上class=one
论颅,又傳遞class=two
哎垦,則最終組件的class= one two
;
原生事件監(jiān)聽
通過在事件上添加.native
可以增加對(duì)原生事件的監(jiān)聽恃疯,如下:
`<my-component v-on:click.native="doTheThing"></my-component>
.sync
修飾符
一般情況下漏设,子組件對(duì)props的修改無法更新到父組件中,但是在2.3.0之后的版本中添加了.sync
修飾符今妄,可以在子組件上更新props郑口,同時(shí)同步到父組件上,如下:
<comp :foo.sync="bar"></comp>
上面這段代碼會(huì)被擴(kuò)展為盾鳞,如下代碼:
<comp :foo="bar" @update:foo=" val => bar = val"></comp>
如果子組件需要更新犬性,則按如下方式即可:
this.$emit('update:foo', newValue);
單向數(shù)據(jù)流
prop綁定數(shù)據(jù)是單向的,當(dāng)父組件的屬性變化時(shí)腾仅,將傳導(dǎo)給子組件乒裆,但是不會(huì)反過來。這是為了防止子組件無意修改了父組件的狀態(tài)——這會(huì)讓應(yīng)用的數(shù)據(jù)流難以理解推励。
另外鹤耍,每次父組件更新時(shí),子組件的所有 prop 都會(huì)更新為最新值验辞。這意味著你不應(yīng)該在子組件內(nèi)部改變 prop稿黄。如果你這么做了,Vue 會(huì)在控制臺(tái)給出警告
使用插槽分發(fā)內(nèi)容(slot)
單個(gè)插槽
注意幾點(diǎn):
- 當(dāng)子組件沒有
slot
插槽時(shí)跌造,父組件調(diào)用子組件時(shí)杆怕,包含的內(nèi)容都會(huì)丟失 - 當(dāng)父組件調(diào)用子組件沒有包含內(nèi)容時(shí),顯示
slot
中的內(nèi)容
示例1:子組件沒有slot
插槽時(shí)
<div>
<h1>我是父組件的標(biāo)題</h1>
<c-child>
<p>這是一些初始內(nèi)容</p>
<p>這是更多的初始內(nèi)容</p>
</c-child>
</div>
// 子組件child的模板鼻听,在該組件中沒有slot财著,因此父組件調(diào)用子組件時(shí)包含的內(nèi)容不會(huì)顯示出來
<template id="child">
<div>
<h2>我是子組件的標(biāo)題</h2>
</div>
</template>
Vue.component("c-child", {
template: "#child"
});
new Vue({
el: "#app-1"
});
上面代碼輸出結(jié)果如下:
當(dāng)在child組件中添加slot,修改為如下代碼:
<template id="child">
<div>
<h2>我是子組件的標(biāo)題</h2>
<slot></slot>
</div>
</template>
顯示結(jié)果如下:
示例2:當(dāng)父組件調(diào)用子組件時(shí),沒有包含內(nèi)容朝墩,則顯示slot中的內(nèi)容
<div>
<h1>我是父組件的標(biāo)題</h1>
<c-child>
</c-child>
</div>
// 子組件child的模板醉拓,在該組件中沒有slot,因此父組件調(diào)用子組件時(shí)包含的內(nèi)容不會(huì)顯示出來
<template id="child">
<div>
<h2>我是子組件的標(biāo)題</h2>
<slot>顯示slot內(nèi)容</slot>
</div>
</template>
Vue.component("c-child", {
template: "#child"
});
new Vue({
el: "#app-1"
});
如下:
具名插槽
<slot> 元素可以用一個(gè)特殊的屬性 name 來配置如何分發(fā)內(nèi)容收苏。多個(gè)插槽可以有不同的名字亿卤。具名插槽將匹配內(nèi)容片段中有對(duì)應(yīng) slot 特性的元素。
也就是說鹿霸,在子組件中可以為slot通過name
屬性定義名字排吴,然后在父組件調(diào)用子組件的時(shí)候,可以通過slot="header"
來為子組件中name="header"
的slot指定內(nèi)容懦鼠,假如指定的name 在子組件中沒有找到钻哩,那么該內(nèi)容將會(huì)被拋棄
// 子組件模板
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
// 父組件
<app-layout>
<h1 slot="header">這里可能是一個(gè)頁面標(biāo)題</h1>
<p>主要內(nèi)容的一個(gè)段落屹堰。</p>
<p>另一個(gè)主要段落。</p>
<p slot="footer">這里有一些聯(lián)系信息</p>
</app-layout>
最終的渲染結(jié)果如下:
<div class="container">
<header>
<h1>這里可能是一個(gè)頁面標(biāo)題</h1>
</header>
<main>
<p>主要內(nèi)容的一個(gè)段落街氢。</p>
<p>另一個(gè)主要段落扯键。</p>
</main>
<footer>
<p>這里有一些聯(lián)系信息</p>
</footer>
</div>
該特性非常有用
作用域插槽
作用域插槽是一種特殊類型的插槽,用作一個(gè)替換已渲染元素的 (能被傳遞數(shù)據(jù)的) 可重用模板珊肃。
在子組件中荣刑,只需將數(shù)據(jù)傳遞到插槽,就像你將 props 傳遞給組件一樣:
<div class="child">
<slot text="hello from child"></slot>
</div>
在父級(jí)中伦乔,具有特殊屬性 scope 的 <template> 元素必須存在厉亏,表示它是作用域插槽的模板。scope 的值對(duì)應(yīng)一個(gè)臨時(shí)變量名烈和,此變量接收從子組件中傳遞的 props 對(duì)象:
<div class="parent">
<child>
<template scope="props">
<span>hello from parent</span>
<span>{{ props.text }}</span>
</template>
</child>
</div>
以上代碼渲染結(jié)果:
<div class="parent">
<div class="child">
<span>hello from parent</span>
<span>hello from child</span>
</div>
</div>
一個(gè)示例:
參考:Vue作用域插槽的使用
動(dòng)態(tài)組件
Vue中的動(dòng)態(tài)組件需要指定一個(gè)掛載點(diǎn)爱只,在該掛載點(diǎn)之下,可以動(dòng)態(tài)的切換組件
用法:
通過<component v-bind:is="currentView"></component>
來調(diào)用組件斥杜,當(dāng)currentView改變時(shí)虱颗,就切換組件,
實(shí)例:
var vm = new Vue({
el: "#example",
data: {
currentView: 'home'
},
// 在該實(shí)例下的組件
components: {
home: { /* home組件 */},
posts: { /* posts組件 */ },
}
});
// 當(dāng)vm.currentView改變時(shí)就進(jìn)行組件切換蔗喂,組件就在當(dāng)前位置進(jìn)行顯示
<component v-bind:is="currentView">
<!-- 組件在 vm.currentview 變化時(shí)改變忘渔! -->
</component>
在使用動(dòng)態(tài)組件進(jìn)行切換時(shí),被切換出來的組件會(huì)被消除缰儿,這樣就存在一個(gè)問題:當(dāng)重復(fù)的切換組件時(shí)畦粮,組件不斷地被消除,然后又重建乖阵,導(dǎo)致性能很差宣赔,這時(shí)可以使用 keep-alive
來使被切換的組件保持在內(nèi)存中,避免了重新渲染瞪浸,keep-alive
的用法如下:
// 只需要添加keep-alive即可
<keep-alive>
<component v-bind:is="currentView">
<!-- 組件在 vm.currentview 變化時(shí)改變儒将! -->
</component>
</keep-alive>
參考: