Vue学习笔记(2)(组件化开发)
Vue2.x學(xué)習(xí)筆記。原視頻教程:最全最新Vue、Vuejs教程,從入門到精通_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili
組件化
1. 什么是組件化?
組件化是Vue.js中的重要思想
-
它提供了一種抽象,讓我們可以開發(fā)出一個個獨立可復(fù)用的小組件來構(gòu)造我們的應(yīng)用。
-
任何的應(yīng)用都會被抽象成一顆組件樹。
組件化思想的應(yīng)用:
-
有了組件化的思想,我們在之后的開發(fā)中就要充分的利用它。
-
盡可能的將頁面拆分成一個個小的、可復(fù)用的組件。
-
這樣讓我們的代碼更加方便組織和管理,并且擴展性也更強。
2. 組件使用的基本步驟
組件的使用分成三個步驟:
創(chuàng)建組件構(gòu)造器:Vue.extend()
注冊組件:vue.component()
使用組件:在Vue實例的作用范圍內(nèi)使用組件
3. 全局組件和局部組件
-
當(dāng)我們通過調(diào)用Vue.component()注冊組件時,組件的注冊是全局的
- 這意味著該組件可以在任意Vue示例下使用。*
-
如果我們注冊的組件是掛載在某個實例中, 那么就是一個局部組件
4. 父組件和子組件的區(qū)分
組件和組件之間存在層級關(guān)系,而其中一種非常重要的關(guān)系就是父子組件的關(guān)系:
**父子組件錯誤用法:**以子標(biāo)簽的形式在Vue實例中使用
-
因為當(dāng)子組件注冊到父組件的components時,Vue會編譯好父組件的模塊
-
該模板的內(nèi)容已經(jīng)決定了父組件將要渲染的HTML(相當(dāng)于父組件中已經(jīng)有了子組件中的內(nèi)容了)
-
<child-cpn></child-cpn>是只能在父組件中被識別的。
-
類似這種用法,<child-cpn></child-cpn>是會被瀏覽器忽略的。
如果想要再使用子組件,必需重新注冊:
let app = new Vue({el:'#app',components:{parent-cpn:parentComponent,child-cpn:childComponent} })5. 組件注冊的語法糖
1)全局組件注冊語法糖
//1.創(chuàng)建組件構(gòu)造器 //const cpn1=Vue.extend()//2.注冊組件(直接省略Vue.extend) vue.component('cpn1',{template:`<div><p>test text</p></div>` })2)局部組件注冊語法糖
const app = new Vue({el:'#app',components:{cpn2:{template:`<div><p>test text</p></div>`}} })6. 組件模板分離寫法
我們通過語法糖簡化了Vue組件的注冊過程,另外還有一個地方的寫法比較麻煩,就是template模塊寫法。
如果我們能將其中的HTML分離出來寫,然后掛載到對應(yīng)的組件上,必然結(jié)構(gòu)會變得非常清晰。
Vue提供了兩種方案來定義HTML模塊內(nèi)容:
-
使用<script>標(biāo)簽
-
使用<template>標(biāo)簽
7. 組件中數(shù)據(jù)的存放
組件無法訪問Vue實例中的數(shù)據(jù),而且即使可以訪問,如果將所有的數(shù)據(jù)都放在Vue實例中,Vue實例就會變的非常臃腫。
因此,Vue組件應(yīng)該有自己保存數(shù)據(jù)的地方。
-
組件對象也有一個data屬性(也可以有methods等屬性,下面我們有用到)
-
只是這個data屬性必須是一個函數(shù)
-
而且這個函數(shù)返回一個對象,對象內(nèi)部保存著數(shù)據(jù)
組件中的data為什么必須是函數(shù)
為什么data在組件中必須是一個函數(shù)呢?
-
首先,如果不是一個函數(shù),Vue直接就會報錯。
-
其次,原因是在于Vue讓每個組件對象都返回一個新的對象,因為如果是同一個對象的,組件在多次使用后會相互影響。
8. 父子組件通信
我們知道子組件是不能引用父組件或者Vue實例的數(shù)據(jù)的。
但是,在開發(fā)中,往往一些數(shù)據(jù)確實需要從上層傳遞到下層:
-
比如在一個頁面中,我們從服務(wù)器請求到了很多的數(shù)據(jù)。
-
其中一部分數(shù)據(jù),并非是我們整個頁面的大組件來展示的,而是需要下面的子組件進行展示。
-
這個時候,并不會讓子組件再次發(fā)送一個網(wǎng)絡(luò)請求,而是直接讓大組件(父組件)將數(shù)據(jù)傳遞給小組件(子組件)。
如何進行父子組件間的通信呢?Vue官方提到:
-
通過props向子組件傳遞數(shù)據(jù)
-
通過事件向父組件發(fā)送消息
1)父傳子 - props
在組件中,使用選項props來聲明需要從父級接收到的數(shù)據(jù)。
props的值有兩種方式:
- 方式一:字符串?dāng)?shù)組,數(shù)組中的字符串就是傳遞時的名稱。
- 方式二:對象,對象可以設(shè)置傳遞時的類型,也可以設(shè)置默認值等。
方式一:
方式二:
當(dāng)需要對props進行類型等驗證時,就需要對象寫法了。
當(dāng)我們有自定義構(gòu)造函數(shù)時,驗證也支持自定義的類型。
關(guān)于props駝峰標(biāo)識:
<div id="app"><!-- 這里不能直接使用cInfo駝峰命名,應(yīng)使用 - 符號 --><cpn :c-info="info"></cpn> </div> <template id="cpn"><h2>{{cInfo}}</h2> </template><script> const cpn={template:"#cpn",props:{cInfo:{ //這里使用駝峰命名法type:Object,required:true}} }const app=new Vue({el:'#app',data:{info:{name:'nick',age:18}},components:{cpn} }) </script>2)子傳父(自定義事件)
什么時候需要自定義事件呢?
-
當(dāng)子組件需要向父組件傳遞數(shù)據(jù)時,就要用到自定義事件了。
-
我們之前學(xué)習(xí)的v-on不僅僅可以用于監(jiān)聽DOM事件,也可以用于組件間的自定義事件。
自定義事件的流程:
-
在子組件中,通過$emit()來觸發(fā)事件。
-
在父組件中,通過v-on來監(jiān)聽子組件事件。
3)結(jié)合雙向綁定
<div id="app"><cpn :number="num" /> </div><template id="cpn"><div><h2>props:{{number}}</h2><h2>data:{{dnumber}}</h2><input type="text" v-model="dnumber"></div> </template><script>const app = new Vue({el: '#app',data: {num: 1,},components: {cpn: {template: '#cpn',props: {//不應(yīng)直接使用props的數(shù)據(jù)number: Number,},//使用data中的數(shù)據(jù)進行雙向綁定data() {return {dnumber: this.number}}}}}) </script>4)父訪問子 - children/children/children/refs
1. $children
this.$children`是一個數(shù)組類型,它包含所有子組件對象。
<div id="app"><cpn></cpn><button @click="btnClick"></button> </div><template id="cpn"><div>我是子組件</div> </template><script>const app = new Vue({el: '#app',data: {},methods:{btnClick(){//打印所有的子組件對象console.log(this.$children);//調(diào)用第一個子組件的方法和屬性this.$children[0].showMsg();console.log(this.$children[0].name)}},components: {cpn: {template: '#cpn',data() {return {name:'children'}},methods:{showMsg(){console.log('子組件msg')}}}}}) </script>2. $refs
$children的缺陷:
-
通過$children訪問子組件時,是一個數(shù)組類型,訪問其中的子組件必須通過索引值。
-
但是當(dāng)子組件過多,我們需要拿到其中一個時,往往不能確定它的索引值,甚至還可能會發(fā)生變化。
-
有時候,我們想明確獲取其中一個特定的組件,這個時候就可以使用$refs
$refs的使用:
-
$refs和ref指令通常是一起使用的。
-
首先,我們通過ref給某一個子組件綁定一個特定的ID。
-
其次,通過this.$refs.ID就可以訪問到該組件了。
5)子訪問父 - parent?parent-parent?root
注意事項:
-
盡管在Vue開發(fā)中,我們允許通過$parent來訪問父組件,但是在真實開發(fā)中盡量不要這樣做。
-
子組件應(yīng)該盡量避免直接訪問父組件的數(shù)據(jù),因為這樣耦合度太高了。
-
如果我們將子組件放在另外一個組件之內(nèi),很可能該父組件沒有對應(yīng)的屬性,往往會引起問題。
-
另外,更不好做的是通過$parent直接修改父組件的狀態(tài),那么父組件中的狀態(tài)將變得飄忽不定,很不利于調(diào)試和維護。
訪問根組件:
使用$root訪問根組件(也就是Vue實例)。
9. 插槽(slot)
slot翻譯為插槽:
-
在生活中很多地方都有插槽,電腦的USB插槽,插板當(dāng)中的電源插槽。
-
插槽的目的是讓我們原來的設(shè)備具備更多的擴展性。
-
比如電腦的USB我們可以插入U盤、硬盤、手機、音響、鍵盤、鼠標(biāo)等等。
組件的插槽:
組件的插槽也是為了讓我們封裝的組件更加具有擴展性。讓使用者可以決定組件內(nèi)部的一些內(nèi)容到底展示什么。
例子:移動網(wǎng)站中的導(dǎo)航欄。
-
移動開發(fā)中,幾乎每個頁面都有導(dǎo)航欄。
-
導(dǎo)航欄我們必然會封裝成一個插件,比如nav-bar組件。
-
一旦有了這個組件,我們就可以在多個頁面中復(fù)用了。
-
但是每個頁面的導(dǎo)航欄又不盡相同。
那如何封裝合適呢?抽取共性,保留不同。
-
最好的封裝方式就是將共性抽取到組件中,將不同暴露為插槽。
-
一旦我們預(yù)留了插槽,就可以讓使用者根據(jù)自己的需求,決定插槽中插入什么內(nèi)容。
-
是搜索框,還是文字,還是菜單。由調(diào)用者自己來決定。
1)slot基本使用
在子組件中,使用特殊的元素<slot>就可以為子組件開啟一個插槽。
該插槽插入什么內(nèi)容取決于父組件如何使用。
2)具名插槽
當(dāng)子組件的功能復(fù)雜時,子組件的插槽可能并非是一個。
-
比如我們封裝一個導(dǎo)航欄的子組件,可能就需要三個插槽,分別代表左邊、中間、右邊。
-
那么,外面在給插槽插入內(nèi)容時,如何區(qū)分插入的是哪一個呢?
-
這個時候,我們就需要給插槽起一個名字
如何使用具名插槽呢?非常簡單,只要給slot元素一個name屬性即可:
<slot name='myslot'></slot>
<body><div id="app"><cpn><!-- 嘗試修改相應(yīng)插槽內(nèi)容 --><span slot="center">標(biāo)題</span><button slot="right">返回</button></cpn></div><template id="cpn"><div><h2>我是子組件</h2><!-- 給插槽命名 --><slot name="left"><span>左邊</span></slot><slot name="center"><span>中間</span></slot><slot name="right"><span>右邊</span></slot></div></template> </body><script>const app = new Vue({el: '#app',data: {},components: {cpn: {template: '#cpn',}}}) </script>3)編譯作用域
我們來考慮上面的代碼是否最終是可以渲染出來的:
-
<my-cpn v-show="isShow"></my-cpn>中,我們使用了isShow屬性。
-
isShow屬性包含在組件中,也包含在Vue實例中。
-
答案:最終可以渲染出來,也就是使用的是Vue實例的屬性。
官方給出了一條準(zhǔn)則:父組件模板的所有東西都會在父級作用域內(nèi)編譯;子組件模板的所有東西都會在子級作用域內(nèi)編譯。
-
而我們在使用<my-cpn v-show="isShow"></my-cpn>的時候,整個組件的使用過程是相當(dāng)于在父組件中出現(xiàn)的。
-
那么他的作用域就是父組件,使用的屬性也是屬于父組件的屬性。
-
因此,isShow使用的是Vue實例中的屬性,而不是子組件的屬性。
4)作用域插槽
作用域插槽是slot一個比較難理解的點,而且官方文檔說的又有點不清晰。
這里,我們用一句話對其做一個總結(jié),然后我們在后續(xù)的案例中來體會:父組件替換插槽的標(biāo)簽,但是內(nèi)容由子組件來提供。
我們先提一個需求:
子組件中包括一組數(shù)據(jù),比如:pLanguages: [‘JavaScript’, ‘Python’, ‘Swift’, ‘Go’, ‘C++’]
需要在多個界面進行展示:某些界面是以水平方向一一展示的;某些界面是以列表形式展示的;某些界面直接展示一個數(shù)組
內(nèi)容在子組件,希望父組件告訴我們?nèi)绾握故?#xff0c;怎么辦呢?利用slot作用域插槽就可以了
我們來看看子組件的定義:
在父組件使用我們的子組件時,從子組件中拿到數(shù)據(jù):
-
我們通過<template slot-scope="slotProps">獲取到slotProps(該名稱隨意)屬性
-
再通過slotProps.data(前面給子組件定義的什么屬性名就用什么,這里子組件用的是:data,所以用.data)就可以獲取到剛才我們傳入的data了
總結(jié)
以上是生活随笔為你收集整理的Vue学习笔记(2)(组件化开发)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SybaseIQ - utility_d
- 下一篇: 如何快速搭建开放、多租户的电商云平台