前言
在我們日常代碼開發程序中,組件的使用是必不可少的,我們也會去封裝組件,但是大家寫組件的風格各式各樣,沒有一個統一的準則,而且也沒有遵循軟體開發的原則:高內聚、低耦合;因為我是給行業提供代碼的,行業給交付提供代碼,我們要盡量去減少大家的接入成本,降低接入成本的最好方案就是我們在設計組件的時候撰寫好檔案,保證職責單一,不要耦合業務,就在很多程度上降低了成本了,在我們平時開發程序中,也遇到過一些組件,一個組件的實作有上千行代碼,那種組件我是直接不想看的,所以我們在開發組件的時候如果你的代碼超過了300行,那你就需要好好思考一下,是否有需要優化的了,設計是否合理,是否有重復的代碼可以封裝等等,
大家在看這個檔案時可以先詳細閱讀一下這個檔案
組件職責單一
比如商品串列篩選條件組件,提供篩選功能,輸出一個選擇的form提供給外部組件請求串列資料,
一個很簡單的功能,為了保證組件的功能的單一,不允許其他模塊往這個組件中新增篩選條件,如果在不修改組件的情況下可以直接使用這個組件
<template>
<!--過濾器-->
<el-form
style="padding-right: 20px"
inline
:model="filter"
ref="filter"
label-position="right"
label-
>
<!-- 關鍵字搜索 -->
<el-form-item label="商品標題:" prop="itemMainTitle">
<el-input
placeholder="請輸入"
size="mini"
v-model.trim="filter.itemMainTitle"
@input="checkFilterParam('itemMainTitle', 80)"
/>
</el-form-item>
<!-- barcode條形碼搜索 -->
<el-form-item v-if="showBarcode" label="條形碼:" prop="barcode">
<el-input
placeholder="條形碼搜索"
prefix-icon="el-icon-search"
size="mini"
v-model.trim="filter.barcode"
@input="checkFilterParam('barcode', 20)"
/>
</el-form-item>
<el-form-item label="商品分類:" prop="categoryId">
<goods-category-cascader
:active-goods-type="goodsType"
:with-all="true"
size="mini"
v-model="filter.categoryId"
:reset-selecte="resetSelecte"
@changeRestStatus="changeRestStatus"
/>
</el-form-item>
<el-form-item label="售賣型別:" prop="saleType">
<el-select v-model="filter.saleType" size="mini" placeholder="售賣型別">
<el-option label="全部型別" :value="https://www.cnblogs.com/fshmjl/p/null"></el-option>
<el-option label="普通售賣" :value="https://www.cnblogs.com/fshmjl/p/SaleChannel.Normal"></el-option>
<el-option label="活動售賣" :value="https://www.cnblogs.com/fshmjl/p/SaleChannel.Activity"></el-option>
</el-select>
</el-form-item>
<!-- 上下架狀態 -->
<el-form-item v-if="showStatus" prop="itemActiveStatus" label="狀態:">
<el-select v-model="filter.itemActiveStatus" size="mini">
<el-option label="全部狀態" :value="https://www.cnblogs.com/fshmjl/p/null"></el-option>
<el-option label="啟用" :value="https://www.cnblogs.com/fshmjl/p/GoodsStatus.PullShelves"></el-option>
<el-option label="禁用" :value="https://www.cnblogs.com/fshmjl/p/GoodsStatus.RemoveShelves"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否支持退款:" prop="notAllowRefund">
<el-select v-model="filter.notAllowRefund" size="mini" placeholder="是否支持退款">
<el-option label="全部狀態" :value="https://www.cnblogs.com/fshmjl/p/null"></el-option>
<el-option label="支持" :value="https://www.cnblogs.com/fshmjl/p/AllowRefund.Yes"></el-option>
<el-option label="不支持" :value="https://www.cnblogs.com/fshmjl/p/AllowRefund.No"></el-option>
</el-select>
</el-form-item>
<el-form-item v-if="showPerformance" label="履約主體:" prop="performanceBuId">
<slot></slot>
</el-form-item>
<el-button type="primary" @click="onFilter">搜索</el-button>
<el-button v-if="!showLabel" plain @click="handleReset" style="margin-top: 2px">重置</el-button>
</el-form>
</template>
體積要小
為了不讓組件去耦合業務,要盡可能的保證組件的純粹性,如上面講到的篩選條件組件,只需要保證輸出的篩選欄位正確性,而篩選的條件的值可以由外部組件提供(如商品分類的資料),
為什么資料要外部傳入?
這是因為一般情況下存在的篩選條件,串列也肯定會有,而有時候后端在回傳資料時只回傳了id,就需要我們去通過id決議出對應的name,這就需要使用到對應的資料,這個時候就可以共享資料,
這樣也可以進一步降低耦合與體積
遵循使用習慣
很多組件都有他們的慣用方法,比如表單組件會使用 v-model 來進行系結表單值、模態框我們會使用visible 或 show() 方法來控制顯示,
遵循這些慣用方法, 可以減少開發者的心智負擔,維持介面的統一性,另外也更容易地被組合/集成(比如在 Ant-design 中 Form.Item 就依賴于這個協議),
舉個例子,頭像選擇器:
export default {
name: 'AvatarSelect',
props: ['avatar'],
methods: {
handleSelect() {
// ...
this.$emit('avatar-change', value)
}
}
}
<avatar-select :avatar="form.avatar" @avatar-change="form.avatar = $event" />
謹防樣式污染
-
每個組件應該有一個命名空間,且這個命名空間最好避免和其他組件沖突,
<template> <div > ... </div> </template> <style lang="scss"> .my-component { // 下級組件樣式 } <style> -
總是開啟 Scoped CSS. 這是一種最簡便的防止污染的方式
<style scoped> .example { color: red; } </style> <template> <div >hi</div> </template> -
CSS 類嵌套不要超過兩級,否則從可讀性和可維護性上都會大打折扣
.foo { .bar { .baz { // 幾百幾千行代碼 } // 幾百幾千行代碼 } } -
推薦使用 BEM 來作為CSS 類名,讓CSS 的語意和組件結構關聯起來,
.my-component { &__head {/*...*/} &__footer {/*...*/} } -
通過 class 或 style 來定制組件的樣式,不要使用直接給標簽加樣式
// ? <el-input /> <style> .el-input { // 樣式覆寫 } </style> // ? <el-input /> <style> .my-input { // 樣式覆寫 } </style>
組件擴展
由于我們是基礎產品,那提供的組件也要盡量豐富,豐富并不是說要在組件中加各種判斷,而是在職責單一、體積、耦合間權衡利弊,也可以創建同型別組件,在同一個檔案index.js中export
單向資料流
-
只通過 props 向下級傳遞狀態,不要通過 ref 這類方式,程序式地去影響下級組件的狀態,
-
下級組件只通過 event 向上級通信,
-
下級組件不準修改 props 源資料,
-
遵循 v-model, update:* 協議,
-
v-model 遵循資料不可變原則,即你不能直接修改 value,而是應該創建一個新的 value,
// 假設 value 是一個串列 handleRemove(item) { const idx = this.value.indexOf(item) if (idx !== -1) { const newValue = https://www.cnblogs.com/fshmjl/p/[...this.value] newValue.splice(idx, 1) this.$emit('input', newValue) } } -
使用 computed 來衍生資料,保持源資料的純潔,
-
分離業務狀態和視圖狀態,比如串列項的激活狀態就是視圖狀態,而后端回傳的資料就是業務狀態,
// 推薦 <item :checked="item.id in checked" @click="checked.add(item.id)" /> // 不推薦: 直接在源資料上添加了一個欄位,污染了原有的資料, <item :checked="item.checked" @click="item.checked = true" />
進階篇
用 JSX 賦能 Vue
Vue 本身是完全支持 JSX 渲染的,但是大部分情況我們還是習慣或者推薦使用模板,
如果你習慣了 React 的 renderProps ,覺得 Vue 的 slot 不夠用,那么可以上 JSX,
使用依賴注入
為了更好點交流和學習,請大家在參閱博客后,留下你的疑問和寶貴意見,謝謝!!!!轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/472298.html
標籤:JavaScript
