好的組件可以極大地提高前端開(kāi)發(fā)效率,而一個(gè)優(yōu)秀的組件應(yīng)該符合以下特性

image.png
一、穩(wěn)定性
組件的穩(wěn)定性,是組件使用的基礎(chǔ),也是前端能實(shí)現(xiàn)快速迭代的必備條件
如何做到穩(wěn)定呢?
- 代碼的執(zhí)行流程必須要可預(yù)期
- 熟知組件的生命周期, 知道該在哪個(gè)鉤子中做什么事
例如:data在create()鉤子中已經(jīng)初始化完畢,故可在此出發(fā)出ajax請(qǐng)求并獲取回傳的數(shù)據(jù)
在mounted()鉤子中實(shí)例已經(jīng)掛載在el上,故可進(jìn)行dom操作(不保證子組件已經(jīng)渲染完成)

image.png
- 覆蓋用戶的所有操作流程,避免因考慮不周全而導(dǎo)致bug
例如:路由的切換會(huì)導(dǎo)致組件重新渲染,如果只是id變了則組件不會(huì)重新渲染,可考慮用beforeRouteUpdate (2.2 新增,路由組件內(nèi)生命周期),
再例如:組件應(yīng)用了keep-alive, 初次渲染組件時(shí)mounted()和activated()都會(huì)被觸發(fā),切換到其它路由的時(shí)候則不會(huì)觸發(fā)destroyed(), 第二次激活組件只會(huì)觸發(fā)activated(),離開(kāi)組件則會(huì)觸發(fā)deactivated(),為了盡可能避免重復(fù)的操作,使代碼流程清晰,我們只在恰當(dāng)?shù)纳芷谧鲈撟龅氖?/li>

image.png
- 少用watch 避免流程不可控
過(guò)多的使用watch會(huì)導(dǎo)致組件變動(dòng)復(fù)雜,如果watch的是一個(gè)對(duì)象且對(duì)象很復(fù)雜,則嘗嘗會(huì)出現(xiàn)某個(gè)地方改變了
該對(duì)象的一個(gè)屬性,則觸發(fā)了watch,這回導(dǎo)致過(guò)多無(wú)用的執(zhí)行,而也許這并不是我們期望的
如果我們?cè)谝粋€(gè)組件內(nèi)watch了很多這樣這樣的對(duì)象,則會(huì)變得異常難以維護(hù),因?yàn)槲覀儫o(wú)法把控觸發(fā)watch的
源頭,特別這個(gè)對(duì)象是用vuex維護(hù)時(shí)
如果不能避免使用watch,要盡快能讓watch函數(shù)邏輯簡(jiǎn)單些
二、一套靠譜的ui組件(自己造或第三方)
在這里推薦餓了嗎 http://element.eleme.io/2.0/#/zh-CN/component/table (最新v2.0)
三、功能單一的組件聚合在一起
- 盡量保證組件的最小化和功能單一化
小到一個(gè)button就是一個(gè)組件 -
將小的組件聚合在一起,實(shí)現(xiàn)特定的功能
例如下圖的tablelist組件 = 工具欄 + 列表 + 頁(yè)碼
image.png
image.png -
規(guī)范的鉤子函數(shù)和參數(shù)(props)
image.png
// tablelist 組件(子組件)
// 獲取遠(yuǎn)程數(shù)據(jù)
searchRemote() {
this.loading = true
// 主動(dòng)獲取數(shù)據(jù)
this.$emit('getBaseList', [
this.pagination,
this.days,
this.startDate,
this.endDate,
this.search_word,
this.sortBy
])
}
// 父組件(調(diào)用方)
searchRemote([pagination, days, startDate, endDate, search_word, sortBy]) {
if (startDate && endDate) {
days = ''
}
// 主動(dòng)獲取數(shù)據(jù)
this.getResultDetail([pagination, this.taskId, days, startDate, endDate, search_word])
}
- 盡量少用$refs
$refs需要直接調(diào)用組件內(nèi)部的方法,如果大量使用,如果組件有變動(dòng)(比如名字或邏輯變了)將導(dǎo)致不可預(yù)期的錯(cuò)誤
四、插槽功能slot(分發(fā))
組件提供數(shù)據(jù)給<slot>,調(diào)用方可重寫<slot>內(nèi)的html

image.png
// tableList組件
<slot name="tableData" :data="filterListData.curPageData" :remotePageData="filterListData"></slot>
// 調(diào)用方(父組件)
<table-list :sortBy="sortBy" :showQuickSearchByDays="true" :showDateRangeSearch="true" :showSearchKey="true" dateRangeSearchPlaceholder="請(qǐng)選擇營(yíng)銷時(shí)間段" @getBaseList="searchRemote" @getFilterList="searchLocal" ref="tableList" :filterListData="resultDetailData">
<template slot="tableData" scope="scope">
<el-table :data="scope.remotePageData" max-height="560" stripe border></el-table>
</template>
</table-list>
五、兼容性
- Autocomplete
小隱患是,可能相鄰父子選擇器會(huì)失效,比方說(shuō).parent > input選擇器,會(huì)因?yàn)槟涿畎职肿儬敔攲?dǎo)致文本框樣式失效,這個(gè)問(wèn)題嘛,改改CSS就可以了;以及多了一個(gè)relative, 元素的z-index層級(jí)管理又更復(fù)雜了一步,維護(hù)成本增加了!
超級(jí)大隱患是,Autocomplete組件下拉框高度超出容器高度是很常見(jiàn)的,但是,由于你外層有了一個(gè)position:relative的父級(jí),只要外面任意一個(gè)容器有overflow:hidden,你的Autocomplete下拉就會(huì)被攔腰斬?cái)啵糠謨?nèi)容不可見(jiàn);如果是overflow:auto/scroll,則會(huì)出現(xiàn)討厭的滾動(dòng)條。這個(gè)組件基本上就廢了!但是,如果沒(méi)有外面這層討厭的position:relative父級(jí),overflow:hidden就干不掉下拉列表,Autocomplete組件就能長(zhǎng)青不老,適用性提升了整整一個(gè)量級(jí)。


