組件概念
一個完整的網頁是複雜的,如果將其作爲一個整體來進行開發,將會遇到下面的困難
- 代碼凌亂臃腫
- 不易協作
- 難以複用
vue推薦使用一種更加精細的控制方案——組件化開發
所謂組件化,即把一個頁面中區域功能細分,每一個區域成爲一個組件,每個組件包含:
- 功能(JS代碼)
- 內容(模板代碼)
- 樣式(CSS代碼)
由於沒有構建工具的支撐,CSS代碼暫時無法放到組件中
組件開發
創建組件
組件是根據一個普通的配置對象創建的,所以要開發一個組件,只需要寫一個配置對象即可
該配置對象和vue實例的配置是幾乎一樣的
//組件配置對象
var myTest = {
data(){
return {
// ...
}
},
computed:{
//...
},
methods:{
//...
},
template: `....`
}
值得注意的是,組件配置對象和vue實例有以下幾點差異:
- 無
el
data
必須是一個函數,該函數返回的對象作爲數據- 由於沒有
el
配置,組件的模板必須定義在template
中
使用組件
使用組件分爲兩步:註冊組件和應用組件
註冊組件:讓組件可以在模板中使用
應用組件:具體的在模板中使用組件
註冊組件
註冊組件分爲兩種方式,一種是全局註冊,一種是局部註冊
- 全局註冊
一旦全局註冊了一個組件,整個應用中任何地方都可以使用該組件
全局註冊的方式是:
// 參數1:組件名稱,將來在模板中使用組件時,會使用該名稱
// 參數2:組件配置對象
// 該代碼運行後,即可在模板中使用組件
Vue.component('my-test', myTest)
在模板中,可以使用組件了
<my-test />
<!-- 或 -->
<my-test></my-test>
但在一些工程化的大型項目中,很多組件都不需要全局使用。
比如一個登錄組件,只有在登錄的相關頁面中使用,如果全局註冊,將導致構建工具無法優化打包
因此,除非組件特別通用,否則不建議使用全局註冊
- 局部註冊
局部註冊就是哪裏要用到組件,就在哪裏註冊
局部註冊的方式是,在要使用組件的組件或實例中加入一個配置:
// 這是另一個要使用my-test的組件
var otherTest = {
components:{
// 屬性名爲組件名稱,模板中將使用該名稱
// 屬性值爲組件配置對象
"my-test": myTest
},
template: `
<div>
<!-- 該組件的其他內容 -->
<my-test></my-test>
</div>
`;
}
應用組件
在模板中使用組件特別簡單,把組件名當作HTML元素名使用即可。
但要注意以下幾點:
- 組件必須有結束
組件可以自結束,也可以用結束標記結束,但必須要有結束
下面的組件使用是錯誤的:
<my-test>
- 組件的命名
無論你使用哪種方式註冊組件,組件的命名需要遵循規範。
組件可以使用kebab-case 短橫線命名法
,也可以使用PascalCase 大駝峯命名法
下面兩種命名均是可以的
var otherTest = {
components:{
"my-test": myTest, // 方式1
MyTest: myTest //方式2
}
}
使用PascalCase
方式命名還有一個額外的好處,即可以在模板中使用兩種組件名
var otherTest = {
components:{
MyTest: myTest
}
}
模板中:
<!-- 可用 -->
<my-test />
<MyTest />
因此,在使用組件時,爲了方便,往往使用以下代碼:
var MyTest = {
//組件配置
}
var OtherTest = {
components:{
MyTest// ES6速寫屬性
}
}
組件樹
一個組件創建好後,往往會在各種地方使用它。它可能多次出現在vue實例中,也可能出現在其他組件中。
於是就形成了一個組件樹
向組件傳遞數據
大部分組件要完成自身的功能,都需要一些額外的信息
比如一個頭像組件,需要告訴它頭像的地址,這就需要在使用組件時向組件傳遞數據
傳遞數據的方式有很多種,最常見的一種是使用組件屬性 component props
首先在組件中申明可以接收哪些屬性:
var MyTest = {
props:["p1", "p2", "p3"],
// 和vue實例一樣,使用組件時也會創建組件的實例
// 而組件的屬性會被提取到組件實例中,因此可以在模板中使用
template: `
<div>
{{p1}}, {{p2}}, {{p3}}
</div>
`
}
在使用組件時,向其傳遞屬性:
var OtherTest = {
components: {
MyTest
},
data(){
return {
a:1
}
},
template: `
<my-test :p1="a" :p2="2" p3="3"/>
`
}
注意:在組件中,屬性是隻讀的,絕不可以更改,這叫做單向數據流
組件實例的生命週期
當我們使用組件時<my-test />
,會創建一個組件的實例,類似於vue實例,每個實例都有明確的生命週期
在生命週期的各個階段,會觸發調用一些函數,這些函數被稱爲生命週期鉤子函數
最常用的兩個鉤子函數:created 和 mounted
- created
created函數發生在注入之後、模板編譯之前,此時,組件還沒有呈現界面
如果有些數據需要經過某些計算得到,可以在這裏進行更改,屆時,在編譯中就會直接應用新的數據
但要注意,由於還未呈現界面,如果在這裏使用了特別耗時的計算,將導致長時間的白屏
- mounted
mounted函數發生在掛載之後,此時頁面已經呈現,在這裏,可以用傳統方案獲取到dom,儘管不太常見
如果某些數據在一開始就需要更新,同時又特別耗時,建議放到mounted中
關於異步代碼
如果某些組件一開始時要執行一些異步代碼(如ajax),created
和mounted
均可,效果差別不大
因爲由於事件循環的機制,會導致異步代碼最終都會在掛載完後調用
但如果異步代碼需要特別長時間的準備(與很多因素有關),則建議放置到mounted中