Vue 之三區域性元件與全域性元件
阿新 • • 發佈:2020-12-17
一:元件化開發基礎
1.元件是什麼?有什麼用?
元件就是:擴充套件 HTML 元素,封裝可重用的程式碼
,目的是複用
例如:有一個輪播圖,可以在很多頁面中使用,一個輪播有js,css,html
元件把js,css,html放到一起,有邏輯,有樣式,有html
元件的分類:
- 全域性元件:可以放在根中
- 區域性元件:
工程化開發之後:
1個元件 就是1個xx.vue
二:元件的註冊方式
1. 定義全域性元件,繫結事件,編寫樣式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>全域性元件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <div @click="handleClick">我是根部元件</div> <global></global> <ul> <li v-for="i in 4"> <global></global> </li> </ul> </div> </body> <script> // 建立1個元件物件(全域性元件) Vue.component('global', {
// global是元件名
// template 是元件的html樣式
// methods 是元件的方法
// data()函式 是存放元件的變數名,在元件中data函式中的變數名要以retun的方式定義
template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px;" @click="handleClick">我是頭部元件</div> <div v-if="isShow">顯示消失</div> </div> `,
methods: { handleClick() { console.log('我被點選了') this.isShow = !this.isShow } },
data() { return { isShow: true } } })
let vm = new Vue({ el: '#box', data: { isShow: true },
methods: { handleClick() { console.log('我被點選了 我是根元件') } } }) </script>
</html>
3. 定義區域性元件
① 區域性元件 放在 Vue例項(根元件) 中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>區域性元件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box" style="max-width: 300px"> <local></local> <global></global> </div> </body> <script> // 建立1個元件物件(全域性元件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;"> 我是全域性元件 </div> </div> `, }) let vm = new Vue({ el: '#box', data: {}, // 建立1個元件物件(區域性元件) components: { local: { // local 元件名 template: ` <div> <div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;" @click="handleClick">我是區域性元件 </div> </div> `, // 元件的模板 methods: { handleClick() { console.log('我被點選了') } } } } }) </script> </html>
② 區域性元件 放在 全域性元件 中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>區域性元件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box" style="max-width: 300px"> <ul> <li v-for="i in 3"> <global></global> </li> </ul> </div> </body> <script> // 建立1個元件物件(全域性元件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;"> 我是全域性的元件 </div> <local></local> <local></local> <br> </div> `, // 建立1個元件物件(區域性元件) components: { local: { template: ` <div> <div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;">我是區域性元件</div> </div> `, } } }) let vm = new Vue({ el: '#box', }) </script> </html>
注意點:
- 定義的元件(body中的位置)必須要放在Vue例項(這也是一個元件 根元件)中
- 區域性元件 必須放在 全域性元件/根元件 中,無法單獨使用
二:元件編寫方式 與 Vue例項的區別
Vue例項(其實,它也是1個元件,是1個根元件)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <ul> <li>字串:{{name}}</li> <li>數值:{{age}}</li> <li><button @click="handleClick()">Click Here</button></li> </ul> </div> </body> <script> let vm = new Vue({ el: '#box', data: { name: 'Darker', age: 18, }, methods: { handleClick() { alert('按鈕被點選') } } }) </script> </html>
元件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>區域性元件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box" style="max-width: 300px"> <ul> <li v-for="i in 3"> <global></global> </li> </ul> </div> </body> <script> // 建立1個元件物件(全域性元件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;"> 我是全域性元件 </div> <local></local> <br> </div> `, // 建立1個元件物件(區域性元件) components: { local: { template: ` <div> <div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;">我是區域性元件</div> </div> `, } } }) let vm = new Vue({ el: '#box', }) </script> </html>
區別:
1.自定義元件需要有1個root element
,一般包裹在 1個div
中
2.父子元件的data
是無法共享的
- 這一點就像Docker的容器一樣,是相互隔離的
- 就算父子的data中資料相同,擁有相同的方法,也是互不影響的
3.元件可以有data、methods、computed....,但是data
必須是一個函式
Vue例項:data是1個鍵值對,用來存放屬性的
var vm = new Vue({ el: '#box', data: { isShow: true } })
元件:data是1個函式,需要有返回值(return
)
Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px;" @click="handleClick">我是頭部元件</div> <div v-if="isShow">顯示消失</div> </div> `, methods: { handleClick() { console.log('我被點選了') this.isShow = !this.isShow } }, data() { return { isShow: true } } })
三:元件通訊
1.父傳子
- 在全域性元件中自定義屬性:
<global :myname="name" :myage="19"></global>
- 在元件中獲取:
{{myname}}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>元件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <!-- myName是自定義屬性 --> <global myname="name" myage="18"></global> <global :myname="name" :myage="19"></global> <global :myname="'Ben'" :myage="20"></global> </div> </body> <script> // 建立1個元件物件(全域性元件/子元件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px;">全域性元件/子元件</div> {{myname}} {{myage}} </div> `, props: ['myname', 'myage'] }) // 父元件 let vm = new Vue({ el: '#box', data: { name: 'darker' }, }) </script> </html>
屬性驗證
- 限制父傳子的變數型別
props: {
myname: String,
isshow: Boolean
}
父傳子時候注意以下區別
<global :myname="name" :myage="19" :isshow="'false'"></global> <global :myname="name" :myage="19" :isshow="false"></global> <global :myname="name" :myage="19" :isshow="isshow"></global>
例項
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>元件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <!-- myName是自定義屬性 --> <!-- <global :myname="name" :myage="19" :isshow="'false'"></global>--> <global :myname="name" :myage="19" :isshow="false"></global> <global :myname="name" :myage="19" :isshow="isshow"></global> </div> </body> <script> // 建立1個元件物件(全域性元件/子元件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px;">全域性元件/子元件</div> <button @click="handleClick">點我顯示/隱藏</button> {{myname}} {{isshow}} </div> `, props: { myname: String, isshow: Boolean } }) // 父元件 let vm = new Vue({ el: '#box', data: { name: 'darker', isshow: true }, }) </script> </html>
3.子傳父(控制子元件的顯示和隱藏)
點選子元件,就會觸發父元件的某個函式執行
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子傳父</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <global @my_event="handleClick($event)"></global> </div> </body> <script> // 建立1個元件物件(全域性元件/子元件) Vue.component('global', { template: ` <div> <div style="background: rgba(255,104,104,0.7); padding: 5px;">全域性元件/子元件</div> <button @click="handleNav">點我</button> </div> `, data() { return { name: 'Darker' } }, methods: { handleNav() { console.log('我是子元件的函式') this.$emit('my_event', 666, 777, this.name) } } }) // 父元件 let vm = new Vue({ el: '#box', data: {}, methods: { handleClick(a,b,c) { console.log('我是父元件的函式') console.log(a) console.log(b) console.log(c) } } }) </script> </html>
小案例
- 子元件有1個按鈕和1個輸入框,子元件輸入完內容後,資料在父元件中展示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子傳父 小案例</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <global @my_event="handleShow($event)"></global> <br> <div>父元件接收到的資料:{{name}}</div> </div> </body> <script> // 建立1個元件物件(全域性元件/子元件) Vue.component('global', { template: ` <div> <input type="text" v-model="myText"> <button @click="handleClick">點我傳資料</button> </div> `, data() { return { myText: '' } }, methods: { handleClick() { this.$emit('my_event', this.myText) } } }) // 父元件 let vm = new Vue({ el: '#box', data: { name: '' }, methods: { handleShow(a) { this.name = a } } }) </script> </html>
4.ref屬性(也可以實現元件間通訊:子和父都可以實現通訊)
- ref放在
標籤
上,拿到的是原生的DOM節點
- ref放在
元件
上,拿到的是元件物件
- 通過這種方式實現子傳父(this.$refs.mychild.text)
- 通過這種方式實現父傳子(呼叫子元件方法傳引數)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子傳父</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <input type="text" ref="myRef"> <button @click="handleButton">點我</button> </div> </body> <script> // 建立1個元件物件(全域性元件/子元件) Vue.component('global', { template: ` <div> <input type="text" v-model="myText"> </div> `, data() { return { myText: '' } }, methods: { handleClick() { this.$emit('my_event', this.myText) this.$emit('my_event', this.innerHTML) } } }) // 父元件 let vm = new Vue({ el: '#box', data: { name: '' }, methods: { handleShow(a) { this.name = a }, handleButton() { console.log(this.$refs) console.log(this.$refs.myRef) console.log(this.$refs.myRef.value) } } }) </script> </html>
5.事件匯流排(不同層級的不通元件通訊)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>子傳父</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <global1></global1> <hr> <global2></global2> </div> </body> <script> // 定義1個時間匯流排 let bus = new Vue({}) // 元件1 Vue.component('global1', { template: ` <div> <h3>元件1</h3> <input type="text" v-model="myText"> <button @click="handleClick1">點我傳遞資料到另一個元件</button> </div> `, data() { return { myText: '' } }, methods: { handleClick1() { console.log(this.myText) bus.$emit('any', this.myText) // 通過事件匯流排傳送 } } }) // 元件2 Vue.component('global2', { template: ` <div> <h3>元件2</h3> 收到的訊息是:{{recvText}} </div> `, data() { return { recvText: '' } }, mounted() { // 元件的掛載(生命週期鉤子函式中的1個),開始監聽時間總線上的:any bus.$on('any', (item) => { console.log('收到了', item,) this.recvText = item }) }, methods: {} }) // 父元件 let vm = new Vue({ el: '#box', data: {}, }) </script> </html>
四:動態元件
1.基本使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>動態元件</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <ul> <li> <button @click="who='child1'">首頁</button> </li> <li> <button @click="who='child2'">訂單</button> </li> <li> <button @click="who='child3'">商品</button> </li> </ul> <component :is="who"></component> </div> </body> <script> let vm = new Vue({ el: '#box', data: { who: 'child1' }, components: { child1: { template: ` <div> <span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是首頁</span> </div> `, }, child2: { template: ` <div> <span style="border-bottom: 5px solid rgba(255,104,255,0.7)">我是訂單</span> </div> `, }, child3: { template: ` <div> <span style="border-bottom: 5px solid rgba(104,255,104,0.7)">我是商品</span> </div> `, } } }) </script> </html>
1.首先什麼是keep-alive?
keep-alive
是一個抽象元件:它自身不會渲染一個DOM元素
,也不會出現在
父元件鏈中;使用keep-alive包裹動態元件
時,會快取不活動的元件
例項,而不是銷燬
它們。簡單理解就是:keep-alive用來快取元件,避免多次載入相應的元件,減少效能消耗。
2.keep-alive的作用
通過設定了
keep-alive
,可以簡單理解為從頁面1跳轉到頁面2後,然後後退到頁面1,只會載入快取中之前已經渲染好的頁面1,而不會再次重新載入頁面1,以及不會再觸發頁面中的created等類似的鉤子函式,除非自己重新重新整理該頁面1。
3.keep-alive的引數
Keep-alive
元件提供了include和exclude兩個屬性,允許元件有條件的進行快取。
include: 字串或正則表示式。只有匹配的元件會被快取。
exclude: 字串或正則表示式。任何匹配的元件都不會被快取。
4.什麼時候用到keep-alive,並且怎麼使用
- 什麼時候用到 keep-alive?
如果需要
頻繁切換路由
,這個時候就可以考慮用keep-alive
了,來達到避免資料的重複請求
的目的。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>keep-alive</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <ul> <li> <button @click="who='child1'">首頁</button> </li> <li> <button @click="who='child2'">訂單</button> </li> <li> <button @click="who='child3'">商品</button> </li> </ul> <keep-alive> <component :is="who"></component> </keep-alive> </div> </body> <script> let vm = new Vue({ el: '#box', data: { who: 'child1' }, components: { child1: { template: ` <div> <span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是首頁</span> </div> `, }, child2: { template: ` <div> <span style="border-bottom: 5px solid rgba(255,104,255,0.7)">我是訂單</span> </div> `, }, child3: { template: ` <div> <span style="border-bottom: 5px solid rgba(104,255,104,0.7)">我是商品</span> </div> `, } } }) </script> </html>
五:slot 插槽
1.基本使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>slot 插槽</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <child> <h6>Hello World</h6> </child> </div> </body> <script> let vm = new Vue({ el: '#box', data: { who: 'child1' }, components: { child: { template: ` <div> <slot></slot> <span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是元件的原內容</span> <slot></slot> </div> `, }, } }) </script> </html>
2.小案例(通過插槽實現在1個元件中控制另1個元件的顯示隱藏)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>slot 插槽</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <!--通過插槽實現在一個元件中控制另一個元件的顯示隱藏--> <child1> <button @click="isShow=!isShow">顯示/隱藏元件2</button> </child1> <child2 v-if="isShow"></child2> </div> </body> <script> Vue.component('child1', { template: `<div> 元件1 <slot></slot> </div>`, }) Vue.component('child2', { template: `<div> <h3>元件2</h3> </div>`, }) var vm = new Vue({ el: '#box', data: { isShow: true } }) </script> </html>
3.具名插槽
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>具名插槽</title> <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script> </head> <body> <div id="box"> <!-- 具名插槽,把p標籤給a插槽,div標籤給b插槽--> <child> <p slot="a">我是具名插槽a插入的內容</p> <div slot="b">我是具名插槽b插入的內容</div> </child> </div> </body> <script> Vue.component('child', { template: `<div> <slot name="a"></slot> <hr> <span style="border-bottom: 5px solid rgba(255,104,104,0.7)">我是元件的原內容</span> <hr> <slot name="b"></slot> </div>`, }) var vm = new Vue({ el: '#box', data: {} }) </script> </html>
可以指定標籤放在某個插槽的位置