提升前端開發(fā)質(zhì)量的十點(diǎn)經(jīng)驗(yàn)沉淀
分享一下平常開發(fā)經(jīng)常出現(xiàn)問題,增加代碼質(zhì)量的十個(gè)小點(diǎn):
記得錯(cuò)誤處理
特別是網(wǎng)絡(luò)請(qǐng)求或者其他異步操作中,await? 記得包裹 try catch?,可以給用戶一個(gè)友好提示,同時(shí)可以考慮 catch 中需要做什么兜底處理,必要時(shí)進(jìn)行上傳日志。
try {
this.loading = this.$loading({
lock: true,
text: '加載中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
});
const info = await resDistributeService({ taskTicketId: this.id });
...
} catch (e) {
this.$message({
type: 'error',
message: e.msg || e.message || '失敗',
});
} finally {
this.loading.close();
}
可以結(jié)合 finally?,處理 loading 等。
數(shù)字 0 的校驗(yàn)
前端經(jīng)常使用 !v? ,來判斷 v 是不是有值。
if(!v){
return
}
doSomething()
但如果 0? 是 v? 的有效值 ,此時(shí)本該處理,但會(huì)提前結(jié)束,最終引發(fā)錯(cuò)誤。此時(shí)需要顯示的判斷是否是 null? 或者 undefined 。
if(v === null || v=== undefined){
return
}
doSomething()
默認(rèn)對(duì)象采用函數(shù)返回
由于 js 中的對(duì)象是引用,因此賦默認(rèn)值的時(shí)候最好通過函數(shù),每次都返回一個(gè)新對(duì)象。
bad:
const defaultCondition = {
name: '',
conditionList: [
{
conditionCode: '',
conditionValue: null,
},
],
}
export default {
data() {
return {
condition: {...defaultCondition},
};
},
methods: {
closeDialog() {
this.condition = {...defaultCondition};
this.configId = null;
this.$refs.form.resetFields();
},
},
};
good:
const getDefaultCondition = () => ({
name: '',
conditionList: [
{
conditionCode: '',
conditionValue: null,
},
],
})
export default {
data() {
return {
condition: getDefaultCondition(),
};
},
methods: {
closeDialog() {
this.condition = getDefaultCondition();
this.configId = null;
this.$refs.form.resetFields();
},
},
};
接口地址單獨(dú)存放
將接口的定義放到統(tǒng)一文件中,未來變動(dòng)改動(dòng)起來會(huì)比較方便,如果各個(gè) url 都寫死在頁面中以后就很麻煩了。
// service.js
import request from 'utils/request';
const service = new (request('/api/m/mallorder/exp/compensation/customer'))();
export const listService = (params) => {
return service.post('/queryRuleList', params);
};
export const listDataKey = 'ruleVOList';
export const idKey = 'ruleId';
export const dialogEnumService = () => {
return service.get('/info');
};
export const saveService = (params) => {
return service.post('/saveRule', params);
};
export const detailService = (params) => {
return service.get('/detail', params);
};
此外,網(wǎng)絡(luò)請(qǐng)求一般都會(huì)在 npm 包的基礎(chǔ)上自己再包一層,一方面可以注入共用參數(shù),另一方面可以對(duì)返回?cái)?shù)據(jù)進(jìn)行統(tǒng)一的錯(cuò)誤處理。
函數(shù)多參數(shù)采用對(duì)象
如果定義一個(gè)函數(shù)需要 3 個(gè)以上的參數(shù)
function(a,b,c,d){
}
此時(shí)可以考慮采用對(duì)象解構(gòu),改為
function({a=1,b,c,d}={}){
}
好處是未來需要擴(kuò)展參數(shù)的時(shí)候,不需要太擔(dān)心其他地方調(diào)用時(shí)候傳參是否會(huì)引起問題。
當(dāng)然,如果參數(shù)過多也需要思考一下當(dāng)前函數(shù)是否承載了太多的功能,進(jìn)行一下功能上的拆分。
函數(shù)單一職責(zé)
當(dāng)我們已經(jīng)定義了一個(gè)函數(shù),比如去初始一些變量。
function initOptions(){
a = xxx
b = xxx
}
此時(shí)我們需要做另一件無關(guān)的事 【A】,雖然它和 initOptions? 調(diào)用的時(shí)機(jī)一致,但最好不要直接放到 initOptions 中,而是新建一個(gè)函數(shù)單獨(dú)調(diào)用。
不然未來如果其他地方也要調(diào) initOptions?,但此時(shí)可能并不需要做【A】這件事情就會(huì)引起 bug。
參數(shù)合法性判斷
由于 js 語言的靈活性,函數(shù)傳入的參數(shù)很可能不符合預(yù)期,必要時(shí)我們需要進(jìn)行判斷并且進(jìn)行兜底處理,不可完全信任調(diào)用方。
團(tuán)隊(duì)合作中,該函數(shù)在未來極大可能會(huì)被其他人調(diào)用。
function doSomeThing(params1, params2) {
if(params1 === null){
return;
}
if(params2){
...
}
// 再去做我們的事情
}
如果后邊的流程強(qiáng)依賴于 params?,我們可以直接 return?,必要時(shí)也可以上報(bào)日志或者 throw Error。
整數(shù)的處理
js? 中沒有整數(shù)類型,即 java? 中的 int、long? 這些,所有數(shù)字都遵循 IEEE 754? 標(biāo)準(zhǔn),即 java? 中的 double? 類型,詳細(xì)的可參考 浮點(diǎn)數(shù)詳解。
可以精確表示的最大整數(shù)是 9007199254740991?,共 16 位,超過這個(gè)數(shù)精度可能會(huì)丟失,對(duì)于新接口,可以問一下后端相應(yīng)數(shù)字字段的最大值會(huì)是多少。
對(duì)于浮點(diǎn)數(shù)的處理,除了眾所周知的 0.1 + 0.2 === 0.3? 的值為 false 外,當(dāng)我們對(duì)數(shù)字進(jìn)行運(yùn)算的時(shí)候也需要注意。
常見的將 9.04? 元轉(zhuǎn)為 904 分:
我們需要對(duì)結(jié)果進(jìn)行取整處理。
可選鏈
可選鏈操作符,參考 MDN ,用的比較多。
和后端定的數(shù)組或者對(duì)象,后端有時(shí)候返回來的很可能是 null 甚至沒有該字段,因此前端可以用可選鏈操作符用于數(shù)組、對(duì)象、函數(shù),防止出現(xiàn)錯(cuò)誤直接阻斷后續(xù)流程。
let nestedProp = obj.first?.second; // 等效于 obj.first && obj.fisrt.second
//后續(xù)流程
但不要過度使用可選鏈,如果某些地方理論上不會(huì)出問題,比如 let test = obj.first?.second?,如果 second? 一定能取到,我們直接 let test = obj.first.second 即可。
不然未來如果這里由于某種原因出了問題導(dǎo)致 obj.first? 是 null?,但我們使用了可選鏈,所以 obj.first?.second 也不會(huì)報(bào)錯(cuò),我們就永遠(yuǎn)不會(huì)知道這里出現(xiàn)問題了。
當(dāng)然也需要權(quán)衡下,不加可選鏈造成 js Error 會(huì)不會(huì)影響業(yè)務(wù)邏輯。
對(duì)象or數(shù)組引用
修改或者使用對(duì)象、數(shù)組時(shí),時(shí)刻切記它們?yōu)橐?,一處修改?huì)造成處處修改。