JustFE团队前端代码规范,降本增效,敏感肌可用

1,185 阅读3分钟

背景 🌏

近年来,接手各个前端的代码,看着前人屎山,深恶痛绝 为了避免自己或者团队,继续添粪,因此经验总结一番~

规范化优点:

  • 容易理解,维护性强
  • 容易编写,扩展性强
  • 精准定位,bug数量减少,容易改
  • 接手难度低,交接容易 从长远来看,降本增效


做法 🤔

🤔那么我们应该怎么做?

回答: 命名统一,遵循原则,其他细节,编写代码

注:以下均为vue3 例子


命名统一 🤓

命名规则:最好由常见的英文单词组合(1~2个)

  • 注释参半:若选择不常见命名,或又难以理解的流程,需简略注释
// 调用接口
const getData = () =>{ return ... }

// 重置清空
const reset = () => { ... }

// 刷新
const refresh = async() => {
  reset();
  await getData();
  // 接口请求完,的后续流程  
  ...
}

// 初始化
const init =() => {
   refresh();
   // 除了接口的,其他初始化流程
}

// 初次加载,先调用一次
init();

// 导出方法
defineExpose({
  reset,
  refresh,
  init,
})

选用通用名,作为方法和参数,团队固定统一

影响:理解UP↑,低门槛接手


四大原则 😎

代码结构化上的一些规则,个人久经沙场,领悟

1、不超千行

单文件遵循 不超千行原则 解决:代码解构,分离样式 > 常量 > 模块(优先级)

样式分离:

<style lang="scss" scoped>
@import "./index.scss";
</style>

常量分离:

import { SORT_CONFIG, FILTER_CONFIG, OTHER_LABEL, 
DATA_RANGE, PREACH_LABEL, USER_STATUS, HOSPITAL_AREA,
UNUSUAL_LABEL,DATA_STRATEGY } from "./constant";

模块分离:

import videoModel from "./model/video";
import audioModel from "./model/audio";
import lessonModel from "./model/lesson";

// 视频资源
const { videoIndex } = toRefs(videoModel.state)

// 音频资源
const { voiceIndex } = toRefs(audioModel.state)

// 课程资源
const { activeList, activeIndex, actionIndex, actionCount, 
actionContinuityTime, lessonPaused, lessonTime, countDown 
} = toRefs(lessonModel.state)

const toActionDetail = () => {
  const id = actionVO.value.id
  const version = actionVO.value.dataVersion
  uni.navigateTo({
    url: `../actionDetail/index?id=${id}&&v=${version}`,
  })
  // 调用课程模块,课程暂停
  lessonModel.lessonPause()
}

要是超千行,按优先级分离:样式 > 常量 > 模块

影响:避免其他参数影响,理解UP↑,定位UP↑,扩展UP↑

2、注释参考

难以理解,注释参考原则

/**
 * 重要说明:
 * @constant: 配置文件
 * @events: 主要事件
 *   onActivated(页面激活时触发/加载页面)
 *   getkeyItem(取值,塞值)
 *   setFilterType(排序、筛选点击事件)
 *   resetAll(重置所有条件)
 *   handleSearch(回传搜索参数 + 搜索)
 */

使用 copilot , 效果更佳

影响:交接难度DOWN↓,理解UP↑

3、策略模式

超双条件(>= 3种条件),使用策略模式原则

<template>
  <div class="list">
     <div class="item" v-for="key in personKeys">
        <span class="item-value">{{personKeys[key].value}}</span>
        <span class="item-title">{{personKeys[key].title}}</span>
     </div>
  </div>
</template>

<script lang="ts" setup>
import { getPersonList } from "@/api/workbench"

const PERSON_CONFIG: any = {
  preachCount: {
    value: 0,
    title: "宣讲量",
  },
  validPreachCount: {
    value: 0,
    title: "有效宣讲量",
  },
  validPreachSuccessCount: {
    value: 0,
    title: "有效宣讲成功量",
  },
}

const personObject: any = ref(deepClone(PERSON_CONFIG));
const personKeys = computed(() => Object.keys(personObject.value));

// 调用接口
const getData = async() => {
  const res = await getPersonList()
  
  if(res.data){
    for (let key in hospObject.value) {
      personObject.value[key].value = res.data[key] || PERSON_CONFIG[key].value;
    } 
  }
}

</script>

多种条件,使用策略模式,结构配置化,更为清晰

影响:定位UP↑,扩展UP↑

4、变量内嵌

template语法内,内嵌 class/style,采取变量内嵌原则

<template>
   <!-- 排序筛选 按钮 -->
  <div class="others">
    <div :class="filterTypeClass('sort')" @click="setFilterType('sort')">
      <span class="icon shuliao icon-L-zhengxu font-14"></span>
      <span class="font-10">排序</span>
    </div>
    <div :class="filterTypeClass('filter')" @click="setFilterType('filter')">
      <span class="icon shuliao icon-L-shaixuan font-14"></span>
      <span class="font-10">筛选</span>
    </div>
  </div>
</template>

<script lang="ts" setup>
 // 选中类型 class
const filterTypeClass = (type: string) => {
  const activeHide = [1, 2].includes(active.value) || (!openBedSort.value && active.value === 0)
  // 排序按钮,显示规则
  const btnHide = type == 'sort' &&  props.pageType === 'yxyyPatient' && activeHide

  return {
    'active': filterType.value === type,
    'hide': btnHide ,
    'pdr-16 others-btn': true,
  }
}  
</script>

尽量避免template语法内,出现多条件判断内嵌class,或者style

抽离至script里,配合注释,标明,更为清晰

影响:交接难度DOWN↓,理解UP↑


其他总结 🤭

在这里插入图片描述


感慨 ❤️‍🔥

不知不觉,入行前端,已经有4年半了

从当初一只小菜鸡,慢慢成长(当然现在还是小菜鸡😄)

看着一直以来的职业道路,道虽曲折,但也有收获

晋升成功后,经历疫情的最后裁员风波,忙于pad端的医疗开发,实在是抽不出时间更新。

看着还是上半年更新的博客,熟悉如往常,我又双叒叕来打破僵局了💪

再提一嘴,copilot是真的好用😍