?目錄總覽:(組件化概念、組件注冊掺栅、數(shù)據(jù)存放烙肺、組件數(shù)據(jù)共享、組件插槽氧卧、使用步驟)
一桃笙、組件化概念
1. 組件化開發(fā)思想
組件化思想的特點:標準、分治沙绝、復用搏明、組合
2. 組件定義
**組件化**開發(fā):根據(jù)封裝的思想,把頁面上可重用的 UI 結(jié)構(gòu)封裝為組件闪檬,從而方便項目的開發(fā)和維護星著。
3. Vue中的組件化開發(fā)
**vue** 是一個**支持組件化開發(fā)的前端框架**。
**vue** 中規(guī)定:**組件的后綴名是 .vue**粗悯。之前接觸到的 App.vue 文件本質(zhì)上就是一個 vue 的組件虚循,即**單組件**(單文件組件)。
4. Vue組件的三個組成部分
每個 .vue 組件都由 3 部分構(gòu)成样傍,分別是:
- template -> 組件的模板結(jié)構(gòu)
- script -> 組件的 JavaScript 行為
- style -> 組件的樣式
其中横缔,每個組件中必須包含 template 模板結(jié)構(gòu),而 script 行為和 style 樣式是可選的組成部分衫哥。
二茎刚、組件注冊
1. 全局組件??
//全局組件使用
<div id="app">
<組件名稱></組件名稱>
</div>
//全局組件注冊
Vue.component(組件名稱, {
data: 組件數(shù)據(jù),
template: 組件模板內(nèi)容
})
- 1.1 全局組件組件可以在app實例內(nèi)部任意地方使用:我們可以在 app 實例下使用,也可以在 home 實例下使用撤逢,也可以在 message 實例下使用膛锭。
<body>
<div id="app">
<div id="home">
<span>首頁</span>
<button-counter></button-counter>
</div>
<div id="message">
<span>消息</span>
<button-counter></button-counter>
</div>
<!--調(diào)用全局注冊組件-->
<button-counter></button-counter>
</div>
<script src="../js/vue.js"></script>
<script>
// 2.定義一個組件(全局組件)
app.component('button-counter',{
data() {
return {
count: 0
}
},
template: `
<button @click="count++">你點擊了{{count}}次</button>`
})
// 1.創(chuàng)建Vue的實例對象
const app = Vue.createApp({
data(){
return {
msg: '你好,Vue3粮坞!'
}
}
});
// 3. 掛載vue實例
app.mount('#app');
</script>
</body>
- 1.2 可以設(shè)置多個全局組件,代碼如下:
<body>
<div id="app">
<div id="home">
<span>首頁</span>
<button-counter></button-counter>
</div>
<div id="message">
<span>消息</span>
<button-counter></button-counter>
<!--調(diào)用第二個注冊組件-->
<lk-box></lk-box>
</div>
<!--調(diào)用全局注冊組件-->
<button-counter></button-counter>
</div>
<script src="../js/vue.js"></script>
<script>
// 1.創(chuàng)建Vue的實例對象
const app = Vue.createApp({
data(){
return {
msg: '你好,Vue3初狰!'
}
}
});
// 2.定義一個組件(全局組件)
app.component('button-counter',{
data() {
return {
count: 0
}
},
template: `
<button @click="count++">你點擊了{{count}}次</button>
`
})
// 定義第二個全局組件
app.component('lk-box',{
template: `
<div style="width: 200px;height: 200px;background-color:pink;">
盒子組件
</div>
`
})
// 3. 掛載vue實例
app.mount('#app');
</script>
</body>
- 1.3 全局組件之間可以相互使用莫杈,使用方式如下:我們在定義第二個全局組件,若向使用第一個全局組件跷究,只需要將第一個全局組件的名稱標簽寫入模板template中即可姓迅。
// 定義第二個全局組件
app.component('lk-box',{
template: `
<div style="width: 200px;height: 200px;background-color:pink;">
盒子組件
<button-counter></button-counter>
</div>
`
})
2. 局部組件??
- 局部組件只能在注冊他的父組件中使用
//局部組件使用
<div id="app">
<ComponentA></ComponentA>
<ComponentB></ComponentB>
<ComponentC></ComponentC>
</div>
//局部組件注冊
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
new Vue({
el: '#app'
components: {
'component-a': ComponentA,
'component-b': ComponentB,
'component-c': ComponentC,
}
})
實例:
//局部組件使用
<body>
<div id="app">
<lk-count></lk-count>
<cc-count></cc-count>
</div>
<script src="../js/vue.js"></script>
<script>
// 注冊一個局部組件
const Counter = {
data() {
return {
count: 0
}
},
template: `
<button @click="count++">你點擊了{{count}}次</button>`
}
// 注冊第二個局部組件
const Box = {
template: `
<div style="width: 200px;height: 200px;background-color:pink;">
盒子組件
</div> `
}
// 創(chuàng)建Vue的實例對象
const app = Vue.createApp({
data(){
return {
msg: '你好,Vue3!'
}
},
// 組件選項
components: {
'lk-count': Counter,
'cc-count': Box
}
});
// 掛載vue實例
app.mount('#app');
</script>
</body>
3. 注意事項
1. data必須是一個函數(shù)
2. 組件模板內(nèi)容必須是單個跟元素
3. 組件模板內(nèi)容可以是模板字符串(需要瀏覽器提供ES6語法支持)
4. 組件命名方式
- 短橫線方式:
Vue.component('my-component', { /* ... */ })
- 駝峰方式:
Vue.component('MyComponent', { /* ... */ })
4.總結(jié)
全局組件:在整個Vue實例中都可以被調(diào)用俊马,若想要全局組件之間相互使用丁存,只需將想使用全局組件的名稱寫入 template 中
局部組件:只能在當前組件中被使用,若想在其他組件中使用柴我,必須使用 components 將其掛載在想使用的組件中解寝,然后再如全局組件那樣向模板template寫入名稱標簽
我們之后其實對局部組件用的更多一些。
三艘儒、組件數(shù)據(jù)存放
Data屬性的值是一個函數(shù)??
- 為什么data在組件中必須是一個函數(shù)呢?
- 當然聋伦,如果不是一個函數(shù),Vue直接就會報錯界睁。
- 組件是可復用的vue實例觉增,一個組件被創(chuàng)建好之后,就可能被用在各個地方
- 而組件不管被復用了多少次翻斟,組件中的data數(shù)據(jù)都應該是相互隔離逾礁,互不影響的
- 基于這一理念,組件每復用一次访惜,data數(shù)據(jù)就應該被復制一次嘹履,之后,當某一處復用的地方組件內(nèi)data數(shù)據(jù)被改變時债热,其他復用地方組件的data數(shù)據(jù)不受影響
- 組件中的data寫成一個函數(shù)砾嫉,數(shù)據(jù)以函數(shù)返回值形式定義,這樣每復用一次組件窒篱,就會返回一份新的data焕刮,類似于給每個組件實例創(chuàng)建一個私有的數(shù)據(jù)空間,讓各個組件實例維護各自的數(shù)據(jù)
- 而單純的寫成對象形式墙杯,就使得所有組件實例共用了一份data济锄,就會造成一個變了全都會變的結(jié)果。
四霍转、組件之間數(shù)據(jù)的交互共享
4.1 父組件向子組件傳值??
1. 組件內(nèi)部通過props接收傳遞過來的值
Vue.component(‘menu-item', {
props: ['title'],
template: '<div>{{ title }}</div>'
})
2. 父組件通過屬性將值傳遞給子組件
<menu-item title="來自父組件的數(shù)據(jù)"></menu-item>
<menu-item :title="title"></menu-item>
3. props屬性名規(guī)則
- 在props中使用駝峰形式,模板中需要使用短橫線的形式
- 字符串形式的模板中沒有這個限制
Vue.component(‘menu-item', {
// 在 JavaScript 中是駝峰式的
props: [‘menuTitle'],
template: '<div>{{ menuTitle }}</div>'
})
<!– 在html中是短橫線方式的 -->
<menu-item menu-title=“nihao"></menu-item>
4. props屬性值類型
- 字符串 String
- 數(shù)值 Number
- 布爾值 Boolean
- 數(shù)組 Array
- 對象 Object
4.2 子組件向父組件傳值??
1. 子組件通過自定義事件向父組件傳遞信息
<button v-on:click='$emit("enlarge-text") '>擴大字體</button>
2. 父組件監(jiān)聽子組件的事件
<menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
3. 子組件通過自定義事件向父組件傳遞信息
<button v-on:click='$emit("enlarge-text", 0.1) '>擴大字體</button>
4. 父組件監(jiān)聽子組件的事件
<menu-item v-on:enlarge-text='fontSize += $event'></menu-item>
4.3 非父子組件間傳值??
1. 單獨的事件中心管理組件間的通信
var eventHub = new Vue()
2. 監(jiān)聽事件與銷毀事件
eventHub.$on('add-todo', addTodo)
eventHub.$off('add-todo')
3. 觸發(fā)事件
eventHub.$emit(‘a(chǎn)dd-todo', id)
五一汽、組件插槽
5.1 組件插槽的作用
插槽就是子組件中的提供給父組件使用的一個占位符避消,用<slot></slot> 表示低滩,父組件可以在這個占位符中填充任何模板代碼,如 HTML岩喷、組件等恕沫,填充的內(nèi)容會替換子組件的<slot></slot>標簽。
父組件向子組件傳遞內(nèi)容
5.2 組件插槽基本用法
//插槽的使用
<div id="app">
<alert-box>有bug發(fā)生</alert-box>
<alert-box>有一個警告</alert-box>
<alert-box></alert-box>
</div>
//插槽的定義
Vue.component('alert-box', {
template: `
<div>
<strong>ERROR:</strong>
<slot>默認內(nèi)容</slot>
</div>`
});
5.3 具名插槽用法
//具名插槽的使用
<div id="app">
//第一種:當具名插槽內(nèi)只有1個標簽
<base-layout>
<p slot='header'>標題信息</p>
<p>主要內(nèi)容1</p>
<p>主要內(nèi)容2</p>
<p slot='footer'>底部信息信息</p>
</base-layout>
//第二種:當具名插槽內(nèi)需要填充多個標簽
<base-layout>
<template slot='header'>
<p>標題信息1</p>
<p>標題信息2</p>
</template>
<p>主要內(nèi)容1</p>
<p>主要內(nèi)容2</p>
<template slot='footer'>
<p>底部信息信息1</p>
<p>底部信息信息2</p>
</template>
</base-layout>
</div>
//具名插槽的定義
Vue.component('base-layout', {
template: `
<div>
<header>
<slot name='header'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name='footer'></slot>
</footer>
</div>`
});
5.4 作用域插槽
//作用域插槽的使用
<fruit-list v-bind:list= "list">
<template slot-scope="slotProps">
<strong v-if="slotProps.item.current">
{{ slotProps.item.text }}
</strong>
</template>
</fruit-list>
//作用域插槽的定義
<ul>
<li v-for= "item in list" v-bind:key= "item.id" >
<slot v-bind:item="item">
{{item.name}}
</slot>
</li>
</ul>