點擊一鍵訂閱《雲薦大咖》專欄,獲取官方推薦精品內容,學技術不迷路!
可重用的代碼可以減少重複勞動。一個軟件中,會有很多類似的業務場景。將這些場景抽象成可重用的代碼。開發新功能時,重用代碼可減少重複勞動。
可重用的代碼可以減少因需求變動,導致多次改動和漏改的情況。試想,要修改全站提交按鈕的顏色,如果全站有100個包含提交按鈕的頁面,每個頁面的按鈕的樣式都沒複用,這改動量和漏改的風險都很大。如果做成可重用的,則只需改動一處。
如何寫出可重用的代碼?
代碼塊的職責越多,越難被複用。寫出可重用的代碼就是:識別,分離出可複用的部分。
考慮這樣的場景:代碼塊A 的功能是獲取接口數據,並渲染 UI。代碼塊B 的 UI 和 A 一樣,但獲取的接口數據不一樣。代碼塊C 獲取的數據和 A 一樣,但 UI 和 A 不一樣。A,B,C 之間的代碼都不能被複用。
要改成可複用的代碼,就是將可複用的 UI,獲取接口數據的代碼獨立出來。
下面,我們來看些常見的可複用的部分和複用方法。
一、UI 展示
UI 展示爲外觀的展示,包含:HTML 和 CSS。不包含數據的獲取和事件處理。
用組件可以實現 UI 展示代碼的複用。這樣的組件被稱爲展示組件。數據和事件處理通過屬性傳入。Ant Design 之類的組件庫裏的組件均爲展示組件。如下是 React 實現的新聞列表:
import React from 'react' import s from './style.scss' import Item, {IItem} from './item' export interface INewsListProps { list: IItem[], onItemClick: (id: number) => void } const NewsList: FC<INewsListProps> = ({ list, onItemClick }) => { return ( <div className={s.list}> { list.map(item => ( <Item key={item.id} onClick={onItemClick} payload={item} /> )) } </div> ) } export default React.memo(NewsList)
二、接口調用
接口調用有兩部分可以複用:
- 接口請求和響應的通用處理。
- 具體接口的調用。
三、接口請求和響應的通用處理
接口調用時,常常要做一些通用的處理。比如:
- 前後端分離的網站,要在接口的請求頭中要加 token 來標識用戶。
- 接口報錯時,要將錯誤碼轉化成對用戶友好的錯誤信息。
用 axios 這麼處理:
// 請求攔截器 axios.interceptors.request.use(...) // 響應攔截器 axios.interceptors.response.use(...)
四、具體接口的調用
接口調用代碼一般會放在一個文件中,如 service.js:
export const fetchList = ... export const fetchDetail = ... export const createItem = ... export const updateItem = ... export const deleteItem = ...
接口調用,還有 Loading 狀態管理,防抖,節流,錯誤重試,緩存等場景。React 可以用 useRequest,Vue 也有類似的輪子。
五、業務流程
很多業務流程是類似的,可以被複用。比如,管理後臺列表頁的業務流程都類似是這樣的:
- 進入頁面時,獲取列表數據。
- 點搜索按鈕,根據當前的查詢條件,獲取列表數據。
- 點分頁,獲取指定頁的列表。
自定義 hooks(Vue3 中叫組合式 API) 支持內部的狀態管理和生命週期。因此,可以用 hooks 來封裝業務流程。下面是用 Vue3 的組合式 API 來封裝管理後臺的列表頁的實現:
import { onMounted, reactive, ref, Ref } from 'vue' export interface Params { url: string searchConditions: Record<string, any> } interface Return<T> { searchConditions: Record<string, any> resetConditions: () => void pagination: Record<string, any> fetchList: (isReset: boolean) => void list: Ref<T[]> isLoading: Ref<boolean> } function useList<T extends Record<string, any>> ({ url, searchConditions: initCondition }: Params): Return<T> { const searchConditions = reactive({...initCondition}) const pagination = reactive({ pageSize: 10 }) const list = ref<T[]>([]) as Ref<T[]> const isLoading = ref(false) as Ref<boolean> // isReset 爲 true 表示搜第一頁。 const fetchList = (isReset: boolean = false): void => ... // 進入頁面 onMounted(() => { fetchList() }) return { searchConditions, pagination, fetchList, list, isLoading, } } export default useList
推薦個 hooks 工具庫:ahooks。Vue 版:ahooks-vue。
六、數據
有些數據指會被多個地方用到。如:登錄的用戶信息,權限數據。
可以用狀態管理庫來管理這些數據。React 狀態管理一般用 Redux,Mobx 或 Context API。 Vue 一般用 Vuex。
七、工具函數
工具函數是與業務無關的。如:格式化日期,生成唯一的 id 等。Lodash 和 moment.js 包含了很多的工具方法。
總結
要寫出可重用的代碼,本質就是識別和分離出可複用的部分。前端可以從 UI 展示,接口調用,業務流程,數據,工具函數 中找出可複用的部分。
代碼質量的下一層次就是:可重構的代碼。我會在下一篇文章中介紹。
金偉強往期精彩文章推薦:
代碼質量第 3 層 - 可讀的代碼
代碼質量第 4 層 - 健壯的代碼
代碼質量第 5 層 - 只是實現了功能
聊聊代碼質量 - 《學得會,抄得走的提升前端代碼質量方法》前言