下面这段代码是同事写的(用了ts),代码能读懂,功能也实现了,但我觉得这种代码不易理解,代码注释少,不知道为什么要这么做,个人感觉这种代码时间一久自己都会忘记当初为什么要这么写
export function initFormConfig (vm: any, ret: any = {}, conf: any = {}, type: any = 'fill') {
PopButton.getBtns(vm, ret, conf, type === 'edit' && !conf.id ? 'new' : type);
let formConfig:any = [];
let viewFormConfig: any = [];
if (['new', 'edit'].includes(type)) {
formConfig = [
{ label: 'ID', key: 'id', compType: 'text' },
// { label: i18n.t('autoPage.Market_Price'), key: '', compType: 'textInput' },
{ label: i18n.t('autoPage.Treasure_Picture'), key: 'thumb', compType: 'imageList', limit: 5, require: true },
{ label: i18n.t('autoPage.Treasure_Price'), key: 'price', compType: 'textInput', require: true },
{ label: i18n.t('autoPage.Treasure_Currency'), key: 'coinId', compType: 'dropdown', i18nMap: ret.coinI18n || {}, require: true },
{ label: i18n.t('autoPage.Commodity_Status'), key: 'status', compType: 'radio', i18nMap: optionMaps.enable, require: true },
{ label: i18n.t('autoPage.Product_Details'), key: 'details', compType: 'tinymce' , require: true},
{
key: 'multiLang', compType: 'multiLang', require: true, forms: [
{ label: i18n.t('autoPage.Baby_Name'), key: 'title', compType: 'textInput' },
{ label: i18n.t('autoPage.Subtitle'), key: 'description', compType: 'textInput' },
],
},
];
}
if (['view', 'viewGoods'].includes(type)) {
viewFormConfig = [
{ label: 'ID', key: 'id', compType: 'text' },
// { label: i18n.t('autoPage.Market_Price'), key: '', compType: 'textInput' },
{ label: i18n.t('autoPage.Treasure_Picture'), key: 'thumb', compType: 'imageList', limit: 5, disabled: true, require: true},
{ label: i18n.t('autoPage.Treasure_Price'), key: 'price', compType: 'text', require: true },
{ label: i18n.t('autoPage.Treasure_Currency'), key: 'coinId', compType: 'dropdown', i18nMap: ret.coinI18n || {}, disabled: true, require: true },
{ label: i18n.t('autoPage.Commodity_Status'), key: 'status', compType: 'radio', i18nMap: optionMaps.enable, disabled: true, require: true },
{ label: i18n.t('autoPage.Product_Details'), key: 'details', compType: 'tinymce', disabled: true, require: true },
{
key: 'multiLang', compType: 'multiLang', require: true, forms: [
{ label: i18n.t('autoPage.Baby_Name'), key: 'title', compType: 'text', require: true },
{ label: i18n.t('autoPage.Subtitle'), key: 'description', compType: 'text', require: true },
],
},
];
}
if (type === 'editStage') {
formConfig = [
{ label: i18n.t('autoPage.Period_Management'), key: 'stage', compType: 'stage', require: true},
];
}
return {
viewForm: viewFormConfig,
checkForm: [],
editForm: formConfig,
};
}
// 初始化表单数据方法
export function initFormData (vm: any, ret: any = {}, conf: any = {}, type: string = 'edit') {
ret.title = conf.id ? `编辑商品` : `新增商品`;
type === 'editStage' && (ret.title = i18n.t('autoPage.Edit_Product_Period'));
if (type === 'editStage') {
return {
id: conf.id || null,
stage: {
count: conf.count || 0,
period: conf.period || 0,
productId: conf.id || null,
stageNo: conf.stageNo || null,
},
};
} else {return {
thumb: conf.thumb && conf.thumb.split(/::divide::/).map((item: string) => ({url: item, name: item})) || [],
thumbInitCopy: conf.thumb && conf.thumb.split(/::divide::/).map((item: string) => ({url: item, name: item})) || [],
id: conf.id || null,
};}
}
export function saveOrUpdate (vm: any, ret: any, conf?: any, type?: string, otherParams?: any, formData?: any) {
let sentDate;
if (['new', 'edit'].includes((type || ''))) {
sentDate = mergeAndDelete(
formData,
['coinId', 'details', 'id', 'price', 'status', 'thumb'],
(res: any, obj: any) =>({
thumb: obj.thumb && obj.thumb.map((item: any) => item.url).join('::divide::'),
// startDate: obj.date[0],
// endDate: obj.date[1]
}),
(res, obj) =>({}),
);
if (!checkBeforeSave(vm, sentDate,[
{check: checkNotNull(sentDate.thumb), fail: '请上传夺宝商品图片'},
{check: checkNotNull(sentDate.coinId), fail: '请选择夺宝币种'},
{check: checkNotNull(sentDate.price), fail: '请输入夺宝价格'},
{check: checkNotNull(sentDate.details), fail: '请输入夺宝详情'},
{check: checkI18nKey(sentDate, 'title', true), fail: '宝贝名称未填写完整'},
{check: checkI18nKey(sentDate, 'description', true), fail: '副标题未填写完整'},
])) {
return true;
}
Api.products.product.post(sentDate).then((res) => {
ret.visible = false;
vm.submitForm('ruleFormRef');
});
} else {
sentDate = mergeAndDelete(
formData,
['id', 'stage', 'flag'],
(res: any, obj: any) =>({}),
(res, obj) =>({}),
);
if (!checkBeforeSave(vm, sentDate,[
{check: checkNotNull(sentDate.stage.count), fail: '请输入开奖注数'},
{check: checkNotNull(sentDate.stage.period), fail: '请输入开奖间隔'},
])) {
return true;
}
formData.flag || Api.products.stage.put({...sentDate.stage}).then((res) => {
ret.visible = false;
vm.submitForm('ruleFormRef');
});
}
return undefined;
}
下面这段代码是我写的,我的代码虽然没有牛逼,但看上去算简洁,每一步都知道在干嘛,为什么要这样做
// 获取alln旅行计划信息
getAllnPlan(){
this.getAllnProductList_action()
.then(({data}) => {
this.loading = false;
let allnProductInfo = {
...data
};
delete allnProductInfo.allnProductConfigList;
this.allnProductInfo = allnProductInfo;
this.allnProductList = data.allnProductConfigList;
let choosedProduct = this.allnProductList[this.activeTab];
this.choosedProduct = choosedProduct;
let investPopupData = this.investPopupData;
investPopupData.minInvestAmount = allnProductInfo.minIncomeRate;
investPopupData.maxInvestAmount = allnProductInfo.maxIncomeRate;
investPopupData.investRate = choosedProduct.investIncome;
investPopupData.investDays = choosedProduct.investDay;
investPopupData.productId = choosedProduct.id;
investPopupData.allnId = choosedProduct.allnId;
this.$nextTick(() => {
this.setTrianglePosition();
});
})
.catch(() => {
this.loading = false;
})
},
// 设置产品列表小三角的位置
setTrianglePosition(){
if(!this.$refs.product_tabs){
return;
}
let productTabs = this.$refs.product_tabs.$el;
let vanTabsNav = productTabs.querySelector('.van-tabs__nav');
let vanActiveTab = productTabs.querySelector('.van-tab.van-tab--active');
let triangles = productTabs.querySelectorAll('.bubble-box-triangle');
let vanTabsNavScrollLeft = vanTabsNav.scrollLeft; // 获取.van-tab父容器滚动条的位置
let vanActiveTabLeft = vanActiveTab.offsetLeft; // 获取当前选中的.van-tab距离父容器最左侧的位置
let vanActiveTabWidth = vanActiveTab.offsetWidth; // 获取当前选中的.van-tab的宽度
let triangleWidth = (triangles[0]).offsetWidth; // 获取三角的宽度
let left = vanActiveTabLeft - vanTabsNavScrollLeft + (vanActiveTabWidth / 2) - (triangleWidth / 2);
/*console.log('vanTabs left',vanActiveTab.offsetLeft)
console.log('vanTabsNavWidth',vanTabsNavScrollLeft)
console.log('left',left)*/
for(let i = 0, len = triangles.length; i < len; i++){
(triangles[i]).style.left = left + 'px';
}
},
// 立即投资按钮点击事件
async investBtnClick(){
let allnAccount = this.get_allnAccount;
if(!allnAccount){
this.$toast(this.$t('common.loadingWait')); //数据加载中,请稍后!
}else {
if(allnAccount.balance === 0 || allnAccount.balance < this.allnProductInfo.minIncomeRate){
this.$toast(this.$t('common.loadingWait')); //资金不足!
return;
}
// 表单校验
let valid = await this.$validator.validate('product_index_investAmount.common_investAmount');
if(!valid){
this.$toast(this.errors.first('product_index_investAmount.common_investAmount'));
return;
}
// 如果popup还未被加载出来,则将popup加载出来
if(!this.investPopupShow){
this.investPopupShow = true;
}
// 取最小投资数量整数倍
this.investAmount = this.$intMultiple(this.investAmount, this.allnProductInfo.minIncomeRate);
this.investPopupVisible = true;
}
},
// 投资成功回调
onInvestSuccess(){
this.getAllnPlan();
},
// 头部组件右上角按钮点击事件
onClickRight(){
this.$router.push({name: 'alln_investAccount'});
}
特此想问问大神们,代码规范应该怎么定?有什么原则?
别的我就不多说了,你们这个用
ts
的话,全部都是any
是什么鬼?这样的话,用和不用有什么区别?一般来讲,如果不是公司有统一的规范要求,就直接用
standard
或者google
以及airbnb
这些比较成熟的代码规范,配合eslint/tslint
和prettier
就可以了,如果觉的规则太繁琐,可以适当的自定义一下,改成适合自己项目和团队的风格即可。一般这种规范属于锦上添花的东西,说句实话,老板是不会看代码写的好不好的,他们只关心代码能不能跑,项目能不能按时上线罢了。以我个人的经验,推行一套规范最难之处在于实施,所以为了保证良好的实时性,最好搭配
CI
等自动化流程工具来约束代码的提交,不要妄想每个人都有意识在提交代码的时候会format
再提交。最后再说点别的,其实我觉的好的代码,或者说可读性高的代码,不是说写满一堆注释,函数划分的无比细致,就是“好”的代码。我所认为的好,通常应该是在设计层和抽象层下功夫,就比如你同事的代码,虽然用了
ts
,全篇都是any
,那直接写js
好了,何必上ts
?反之,如果类型的设计和语义十分准确,同时业务层代码也引用了这些类型,那即使没有任何注释,相同水平的程序员也可以根据这些类型猜个八九不离十了。所以我觉的,正确的使用工具,才是你们团队现在最应该考虑的问题。