-
什么是組件化
將一個完整的頁面分成很多個組件,每個組件用于實現(xiàn)頁面的一個功能塊,每一個組件又可以細(xì)分。 -
組件化基本使用
-
組件化使用三個步驟:
1.創(chuàng)建組件構(gòu)造器
2.注冊組件
3.使用組件
組件化使用步驟
-
<div id="app">
<!-- 3.使用組件-->
<my-cpn></my-cpn>
</div>
<script>
// 用``定義字符串可以換行
// 1.創(chuàng)建組件構(gòu)造器對象
const cpnC = Vue.extend({
template: `
<div>
<h2>我是標(biāo)題1</h2>
<p>我是內(nèi)容111</p>
<p>我是內(nèi)容222</p>
</div>`
})
// 2.注冊組件
Vue.component('my-cpn', cpnC);
const app = new Vue({
el: '#app',
data: {
}
})
</script>
-
全局組件
全局組件:
// 注冊組件(全局組件),可以在多個vue實例下使用
Vue.component('my-cpn', cpnC);
局部組件:
const app = new Vue({
el: '#app',
data: {
},
// 注冊局部組件,只能在該vue實例中使用
components: {
my_cpn: cpnC
}
})
- 父組件和子組件
<div id="app">
<my_cpn2></my_cpn2>
</div>
<script>
// 創(chuàng)建第一個組件構(gòu)造器(子組件)
const cpn_c1 = Vue.extend({
template:`
<div>
<h2>標(biāo)題1</h2>
<p>內(nèi)容1</p>
</div>`
})
// 創(chuàng)建第二個組件構(gòu)造器(父組件)
const cpn_c2 = Vue.extend({
template:`
<div>
<h2>標(biāo)題2</h2>
<p>內(nèi)容2</p>
<my_cpn1></my_cpn1>
</div>`,
// 在組件2中注冊組件1,就可以在組件2中使用組件1
components: {
my_cpn1: cpn_c1
}
})
const app = new Vue({
el: '#app',
data: {
},
components: {
my_cpn2: cpn_c2
}
})
</script>
- 注冊組件語法糖和組件模板抽離寫法
<div id="app">
<my-cpn1></my-cpn1>
<my_cpn2></my_cpn2>
</div>
<template id="my-cpn">
<div>
<h2>我是標(biāo)題1</h2>
<p>我是內(nèi)容111</p>
</div>
</template>
<script>
// 注冊全局組件
Vue.component('my-cpn1', {
template: '#my-cpn'
});
const app = new Vue({
el: '#app',
data: {
},
// 注冊局部組件,只能在該vue中使用
components: {
'my_cpn2': {
template: '#my-cpn'
}
}
})
</script>
- 組件中的data和方法
<div id="app">
<my_cpn></my_cpn>
<my_cpn></my_cpn>
</div>
<template id="cpn">
<div>
<h2>當(dāng)前計數(shù):{{counter}}</h2>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script>
const app = new Vue({
el: '#app',
components: {
'my_cpn': {
template: '#cpn',
// 存放組件的數(shù)據(jù)
data() {
return {
counter: 0
}
},
methods: {
increment() {
this.counter ++;
},
decrement() {
this.counter --;
}
}
}
}
})
</script>
-
組件通信
1.父傳子props
父子組件通信
在組件中使用props來聲明需要從父級接收的數(shù)據(jù)
props的值有兩種方式:
方式一:字符串?dāng)?shù)組,數(shù)組中的字符串就是傳遞時的名稱
方式二:對象,對象可以設(shè)置傳遞時的類型,也可以設(shè)置默認(rèn)值等
function Person(name){
this.name = name
}
Vue.component('my-conmponent', {
props: {
// 基礎(chǔ)類型檢查(null匹配任何類型)
itemA: Number,
// 多個可能的類型
itemB: [String, Number],
// 必須傳的
itemC: {
type: String,
required: true
},
// 有默認(rèn)值的
itemD: {
type: String,
default: 'ABC'
},
// 有默認(rèn)值的數(shù)組
itemE: {
type: Array,
default() {
return [];
}
},
// 有默認(rèn)值的對象
itemF: {
type: Object,
default() {
return {message: 'hello'}
}
},
// 自定義驗證函數(shù)
itemG: {
validator(value) {
return ['success','warning','danger'].indexOf(value) !== -1
}
},
// 驗證自定義類型
itemH: Preson
}
})
舉例:
<div id="app">
<my_cpn v-bind:cmovies="movies" :msg="message"></my_cpn>
</div>
<template id="cpn">
<ul>
<li v-for="item in cmovies">{{item}}</li>
</ul>
<h3>{{msg}}</h3>
</template>
<script>
const my_cpn = {
template: '#cpn',
// props: ['cmovies', 'msg']
props: {
// 1.類型限制
// cmovies: Array,
// msg: String
// 2.提供默認(rèn)值
msg: {
type:String,
default: 'hi',
// 必傳值(要使用my_cpn組件,必須傳msg)
required: true
},
cmovies: {
type: Array,
default() {
return []
}
}
}
}
const app = new Vue({
el: '#app',
data: {
movies: ['送你一朵小紅花', '金剛川', '少年的你'],
message: 'hello'
},
components: {
my_cpn
}
})
</script>
2.子傳父
<div id="app">
<my_cpn @item-click="in_cpn_click"></my_cpn>
</div>
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script>
// 子組件
const my_cpn = {
template: '#cpn',
data() {
return {
categories: [
{id: 1, name: '熱門推薦'},
{id: 2, name: '手機數(shù)碼'},
{id: 3, name: '美妝護(hù)膚'}
]
}
},
methods: {
btnClick(item) {
console.log(item.name + '被點擊');
// 告訴父組件被點擊的是哪一個item
// 發(fā)射事件
this.$emit('item-click', item)
}
}
}
// 父組件
const app = new Vue({
el: '#app',
components: {
my_cpn
},
methods: {
in_cpn_click(item) {
console.log('子組件中的' + item.name + '被點擊');
}
}
})
</script>
-
組件訪問
1.父訪問子
<div id="app">
<cpn></cpn>
<!-- refs方式需要在使用組件時,添加ref屬性 -->
<cpn ref="cpn2"></cpn>
<button @click="btnClick()">按鈕</button>
</div>
<template id="cpn">
<div>我是子組件</div>
</template>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello world'
},
methods: {
btnClick() {
// $children較少用,一般用refs
// console.log(this.$children);
// this.$children[0].showMessage()
// console.log(this.$children[0].name)
console.log(this.$refs.cpn2.name);
this.$refs.cpn2.showMessage();
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: 'Naruto'
}
},
methods: {
showMessage() {
console.log('showMessage');
}
},
}
}
})
</script>
2.子訪問父
不建議使用
-
組件的插槽
組件的插槽是為了讓我們封裝的組件更具擴展性,讓使用者可以決定組件內(nèi)部的一些內(nèi)容到底展示什么。
將共性抽取到組件中,將不同暴露為插槽??梢宰屖褂谜吒鶕?jù)自己的需求,決定插槽中插入的內(nèi)容。
<div id="app">
<cpn><button>按鈕</button></cpn>
<cpn><span>哈哈哈</span></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是組件標(biāo)題</h2>
<p>我是組件內(nèi)容</p>
<!-- 插槽即預(yù)留一些空間,使用時可以在組件中插入其它標(biāo)簽 -->
<!-- <slot></slot> -->
<!-- 如果使用時沒有插入標(biāo)簽,則默認(rèn)顯示插槽中的標(biāo)簽 -->
<slot><button>插槽默認(rèn)按鈕</button></slot>
</div>
</template>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello world'
},
components: {
cpn: {
template: '#cpn'
}
}
})
</script>

插槽
- 具名插槽
<div id="app">
<!-- 替換沒有name的slot -->
<cpn><span>span</span></cpn>
<cpn>
<template v-slot:left>
<span>替換左邊slot</span>
</template>
<template v-slot:right>
<span>替換右邊內(nèi)容</span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<h2>組件標(biāo)題</h2>
<p>組件內(nèi)容</p>
<slot name="left">左邊</slot>
<slot name="center">中間</slot>
<slot name="right">右邊</slot>
<slot></slot>
</div>
</template>
<script>
const app = new Vue({
el: '#app',
components: {
cpn: {
template: '#cpn'
}
}
})
</script>

具名插槽
-
作用域插槽
父組件替換插槽的標(biāo)簽,但是內(nèi)容由子組件來提供。
<!-- 父組件替換插槽的標(biāo)簽,但是內(nèi)容由子組件來提供 -->
<div id="app">
<cpn></cpn>
<cpn>
<!-- 獲取子組件中的pLanguages -->
<template v-slot:default="slotProps">
<span v-for="item in slotProps.languages">{{item}} - </span>
</template>
</cpn>
</div>
<template id="cpn">
<div>
<!-- 將子組件的數(shù)據(jù)傳給父組件 -->
<slot :languages="pLanguages">
<ul>
<li v-for="item in pLanguages">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script>
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn: {
template: '#cpn',
data() {
return {
pLanguages: ['JavaScript', 'Java', 'Python', 'c++', 'go', 'Swift']
}
}
}
}
})
</script>


