Vue2屎山代码大盘点

2023-11-18

前言

相比其他的框架来说,Vue中更容易产出屎山代码;因为Vue中的options就是一个大对象,导致js本身的很多检测都失效了,比如一个函数没有用到的话会“变灰”,template中代码提示比较少,较多的mixins等等;遇到屎山代码,大多数人第一反应就是这谁写的代码这么差,其实大多数公司大多数人至少曾经都写过一些屎山代码,有屎山代码很正常,问题在于怎么快速梳理出业务逻辑,防止在迭代新需求时引发bug,在富有余力的情况下可以进行局部重构,渐进式优化屎山代码;

今天重点就看一看Vue2中的那些屎山;

通用屎山

一号屎山–目录杂乱

危害程度:⭐️

src/
├── App.vue
├── api
├── components
├── constants
├── main.js
├── pages
├── router
├── services
├── utils
│   └── hash.js
└── views

看一下上面的目录,views和pages是类似的含义,都是指的路由对应的页面,而api和services也是类似的都是存放后端接口的封装,同时存在这几种文件夹说明项目初期没有规范,每个人按照自己的规范去开发,导致有的人页面写在views里面,有的写在pages里面,建议这几个相似含义的目录只保留一个;

一号屎山的危害在于让后续接手的人要频繁切换文件夹去看不同页面的逻辑,并且不知道后续自己应该在哪个文件夹开发自己的页面,导致恶性循环;

二号屎山–奇葩命名法

危害程度:⭐️⭐️⭐️⭐️⭐️

奇葩命名法有以下几种情况:

  • 全拼音命名法
    ”毕竟都是中国人嘛,全拼音命名大家应该都看得懂吧“,举个例子:dazhe.vue。但是同一个拼音可以翻译出不同的意思出来,他们之间是一对多的关系,因此不适合作为组件名;当然,全拼音命名还算是手下留情的,有的时候全拼音命名可能会很长,那就直接取首字母吧!

  • 拼音首字母命名法
    于是dazhe.vue变成了dz.vue,这个时候就成了猜谜语,有一首歌词写得好:女孩的心思男孩你别猜别猜别猜你猜来猜去也猜不明白,到了这里就是代码的心思你别猜,直接放弃吧!

  • 中西合璧命名法
    有些同学觉得光中文那不太高大上啊,要把英语也加进来才能显示自己的水平,所以这样命名:dzList.vue,照样还是让人看不懂

  • 英文首字母命名法 我想这种方式命名的同学应该不多吧,毕竟已经拿起翻译工具翻译了,直接cv就可以了,为什么还要摘出首字母来呢?

上面举了文件名作为例子,其实命名规范充斥在所有程序员的每一项工作中,比如:变量命名、函数命名、类命名、接口命名,以我之见,严格遵循命名规范是编程的第一步,必须使用翻译的英文来命名,英文就是一个字典,至少大部分的英文通过翻译之后还是能够准确地知晓其含义的,这里面错误的概率远远低于以上几种方式;

三号屎山–组件不拆分

危害程度:⭐️⭐️⭐️⭐️⭐️

Vue将template、script、style组合在一个.vue文件中,这天然就会使得每一个.vue文件的行数会非常多,难以维护,Vue2中一个最明显的屎山就是几千行、甚至上万行的代码,用专业的术语来讲就是不符合单一职责原则,一个组件应该只干一件事情,一个函数应该只处理一个逻辑,剩下的逻辑交给其他函数或者组件来做;时刻牢记“SOLID”原则是远离屎山的第一心法;

前面通用屎山已经堆积到一定高度,接下来再加大马力,看看template屎山、script屎山和style屎山。

template屎山

四号屎山–复杂的表达式

危害程度:⭐️⭐️⭐️

 <div
    class="files"
    :class="{ disabled: !isAllowRead && hasNotPassed && aaa && (bbb || ccc) }"
    @click="toDetail()"
  >
  <a/>
  <b v-if="!isAllowRead && hasNotPassed && aaa && (bbb || ccc)"/>
 </div>

看这一段代码,为了判断一个禁用状态,使用了大量的运算符,导致逻辑不清晰,并且遇到相似的逻辑在下面b组件上不得不ctrl cv,妥妥地变成了cv工程师,这里正确的做法是应该放到计算属性里面去进行判断,并且根据后面所使用到的逻辑进行计算属性的拆分:

     <div
        class="files"
        :class="{ disabled: isFileDisabled }"
        @click="toDetail()"
      >
      <a/>
      <b v-if="isFileDisabled"/>
     </div>
     <script>
         export default {
             // 此处省略...
             computed: {
+              isFileDisabled(){
+                 return !isAllowRead && hasNotPassed && aaa && (bbb || ccc)
+              }
             }
         }
     </script>

当然isFileDisabled这个计算属性也可以拆分成多个,这个主要看后续的复用情况;所以二号屎山的优化方案就是利用计算属性或者拆分计算属性

五号屎山–大量重复节点

危害程度:⭐️⭐️⭐️

<template>
  <div>
    <span>姓名:{{ name }}</span>
    <span>年龄:{{ age }}</span>
    <span>性别:{{ gender }}</span>
    <span>身高:{{ height }}</span>
    <span>体重:{{ weight }}</span>
    <span>爱好{{ habit }}</span>
  </div>
</template>

优化后的代码:

  <div>
+    <span v-for="item in textConfigs" :key="item.valueKey">{{
+      response[item.valueKey]
+    }}</span>
  </div>
  
  data() {
    return {
+      textConfigs: [
+        { label: "性别", valueKey: "name" },
+        { label: "年龄", valueKey: "age" },
+        { label: "性别", valueKey: "gender" },
+        { label: "身高", valueKey: "height" },
+        { label: "体重", valueKey: "weight" },
+        { label: "爱好", valueKey: "habit" }
+      ]
    };
  },

可能有些同学认为这个不算是屎山代码,但是当这个span变得复杂起来之后甚至这个span里面包含了几十行代码的时候,就会发现这里面的重复元素太多了,进而无法维护;

script屎山

六号屎山–if else switch

危害程度:⭐️⭐️

if(!values.username){
    this.$message.error("用户名不能为空")
} else if(!values.password){
    this.$message.error("密码不能为空")
} else if(!values.phoneNumber){
    this.$message.error("手机号不能为空")
} else {
    this.submit();
}

可能有人会说,上面的代码语义明确,写得还不够好吗?但是如果需要增加更多的校验条件时,开发者不得不侵入到具体方法去修改代码,使用策略模式优化之后能够让校验条件与具体判断逻辑解耦,当需要增加校验条件时直接修改数组即可

const validators = [
  { message: "用户名不能为空", required: true, key: "username" },
  { message: "密码不能为空", required: true, key: "password" },
  { message: "手机号不能为空", required: true, key: "phoneNumber" }
];

export default {
  methods: {
    validator(values) {
      const result = validators.some(el => {
        if (el.required && !values[el.key]) {
          this.$message.error(el.message);
          return true;
        }
      });
      return result;
    },
    submit(values) {
      if (this.validator(values)) {
        return;
      }

      // ... 调用接口
    }
  }
};

七号屎山–后端参数处理

危害程度:⭐️⭐️⭐️

    handleParams() {
      const params = {};
      params.id = this.formItem.id;
      params.startDate = this.formItem.startDate.format("YYYY-MM-DD");
      params.endDate = this.formItem.endDate.format("YYYY-MM-DD");
      params.price = this.formItem.price.toString();
      params.type = this.formItem.type;
      params.total = this.formItem.total;
      params.name = this.formItem.name;
      params.comment = this.formItem.comment;
      // ... 此处省略一万行代码
    }

看到这样的代码内心是崩溃的,明显只有几个字段需要处理一下却把所有字段都赋值了一遍,可以这样简化:

    handleParams() {
      const { startDate, endDate, price, ...params } = this.formItem;
      params.startDate = startDate.format("YYYY-MM-DD");
      params.endDate = endDate.format("YYYY-MM-DD");
      params.price = price.toString();
      // ... 此处省掉一万行代码
    }

八号屎山–硬编码

危害程度:⭐️⭐️⭐️⭐️

  computed: {
    isGood() {
      return this.type === 1;
    },
    isBad() {
      return this.type === 0;
    }
  }

看上面的例子,这种硬编码基本随处可见,作者在写这段代码的时候肯定是觉得这个type只会在这里用到,没有必要单独定义一个常量来管理,后面接收的同学来了他也不会去关注之前的逻辑,他只要用到了type又会去重新判断一下是good还是bad,就这样最后代码中充斥着0,1,2,3这样的数字,后来新人接到一个需求并且涉及到这些数字背后的含义这个时候就不得不去一个一个地询问原作者了,好的做法就是写成常量配置文件,单独写一个文件config.js,然后组件去引用这个常量:

// 货物的品质枚举值
export const GOODS_TYPE = {
  good: 1, // 质量好
  bad: 0   // 质量差
};

九号屎山–Mixins屎山

危害程度:⭐️⭐️⭐️

我不生产代码,我只是Mixins的搬运工:

// a.mixin.js
export default {
  data() {
    return {
      username: "",
      password: "",
      age: 18
    };
  },
  created() {
    this.fetchUserInfo();
  },
  methods: {
    fetchUserInfo() {}
  }
};

// b.mixin.js
export default {
    data(){
        return {
            height:'',
            weight:''
        }
    },
    created(){
        this.fetchBodyFat();
    },
    methods:{
        fetchBodyFat(){

        }
    }
}

// c.vue
const DEGREEMAP = {
    doctor:'博士'
}
export default {
    mixins:[a,b],
    data(){
        return {
            degree:DEGREEMAP.doctor
        }
    },
    created(){
        this.log()
    },
    methods:{
        log(){
            if(this.age < 30 && this.height>180 && this.degree===DEGREEMAP.doctor){
                alert("真牛!")
            }
        }
    }
}

这里a、b提供了一些数据,最后统一在c.vue中使用,这样的话容易造成变量覆盖以及来路不明等问题,如果必须使用vue2的话这种情况是避免不了的,只能尽量减少组件对mixins中data的耦合度,但是最近看到一篇文章打开了新的思路,有兴趣的可以读一读:
我可能发现了Vue Mixin的正确用法——动态Mixin

十号屎山–无用代码不删除

危害程度:⭐️⭐️

大段注释不删除,没用的methods也不注释,本着多一事不如少一事的原则,因为Vue中父组件调用子组件方法比较常见,因此有些方法不使用了,自己也不去注释或者删除,害怕引发其他bug,或者干脆就不管,直接写一个其他名称的方法

无用的文件不删除,比方说开始定义了一个list.vue,后面这个文件重构了,直接增加了一个List.vue,目录中同时存在这两个文件,让人摸不着头脑,无形增加了项目复杂度,试想一下如果一个超大项目,一半的文件都是没有引用到的,那是多么的可怕!

style屎山

十一号屎山–类名无规范

危害程度:⭐️

将id,驼峰、横线、下划线结合使用:

css复制代码#id{}
#App{}
.AppBuy{}
.app-buy{}
.app_buy{}
.App_Buy{}

好的css是有一定的规范的,禁止使用id选择器、!important;类名用横线分割,或者参考BEM规范

十二号屎山–样式大量重复

危害程度:⭐️

css复制代码.a{
    display:flex;
    align-items:center;
    justify-content:center;
}
.b{
     display:flex;
     align-items:center;
     justify-content:center;
     font-size:16px;
     color:red;
}

css样式大量重复导致css文件体积剧增,特别是在样式基本固定的后台系统中,写样式其实是一个痛苦的事情,因此最好是做到原子化公共样式与业务具体样式的分离

最后一个屎山–不写注释

危害程度:⭐️⭐️⭐️⭐️⭐️

写个注释是举手之劳,花不了多少时间,而且前面所有的屎山堆起来,如果有注释的话还是可以快速理解其含义的,但是如果再加上不写注释,那就是天坑了,谁也救不了这个屎山;

罗马的道路不是一日铺成的,屎山的代码也不是一天写成的,而是在每个开发者无所谓的心态下堆成的,如果平时多注意注意至少也能保证自己写的代码”留有余香“。

建议读完本文之后再读一读参考文章,最后是严格地执行!如果以时间不够为借口而不执行那么看再多的文章也没有用!
堆屎山没有终点,持续更新中…

十四号屎山–组件不写name

危害程度:⭐️

js复制代码// temp.vue

<template>
  <div>
    temp
  </div>
</template>
<script>
export default {};
</script>

// App.vue
<template>
    <div id="app">
        <my-component/>
    </div>
</template>
<script>
import MyComponent from "@/components/temp";

export default {
     components: {
        MyComponent
     },
};
</script>

temp组件不写name,然后导入的时候随便设置一个其他的名字,在父组件中使用,这样在vue-devtools中查看的话,组件名为MyComponent,如果只有这样一个组件问题不大;想一下所有组件都不设置name,然后从根组件开始每一层组件都有一个叫Button的组件,一个新人接手这个项目了,他用devtool打开一看全是Button组件,看起来貌似是一样但是其实不一样,而且要搞清楚到底对应的代码在哪里还很费时间;如果定义了name,那么即使改变注册的key,组件名也是固定的,另外推荐组件名与文件名一致,这样大大地降低了组件搜索成本;

转载与 : https://juejin.cn/post/7246686667750785083

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue2屎山代码大盘点 的相关文章

随机推荐

  • git第一次配置ssh key,clone代码出错解决方法

    错误 The authenticity of host can t be established ED25519 key fingerprint is SHA256 k4ViHJBFryacGI BqHphyjDBaRLwt5eSGRMJG
  • vue table合并行 动态列名

    需求 1 合并行 相同数据合并 2 根据后端返回数据动态显示列名 我这个业务需求是 每年增加一列 也就是列名不是固定的 后端返回数据每年会多一条数据 根据返回数据显示列名 实现 html
  • 论文阅读 StyleCLIP:《StyleCLIP: Text-Driven Manipulation of StyleGAN Imagery》

    论文地址 https arxiv org pdf 2103 17249 pdf 文章目录 摘要 1 介绍 2 相关工作 2 1 视觉与语言 2 2 潜空间图像处理 3 StyleCLIP文本驱动操作 4 潜在优化 5 潜在映射 6 全局方向
  • 解密蓝牙mesh系列

    转载自 蓝牙技术联盟 蓝牙mesh网络 友谊篇 低功耗蓝牙 Bluetooth Low Energy 是全球最具节能性的短距离无线通信技术之一 其低功耗的特性广受开发者和消费者赞誉 随着蓝牙mesh网络的推出 开发者可能想知道蓝牙mesh网
  • Python3 如何优雅地使用正则表达式(详解五)

    非捕获组命名组 精心设计的正则表达式可能会划分很多组 这些组不仅可以匹配相关的子串 还能够对正则表达式本身进行分组和结构化 在复杂的正则表达式中 由于有太多的组 因此通过组的序号来跟踪和使用会变得困难 有两个新的功能可以帮你解决这个问题 非
  • 线性稳压器基础知识

    1 1 什么是线性稳压器 线性稳压器的工作原理是 采用一个压控电流源以强制在稳压器输出端上产生一个固定 电压 控制电路连续监视 检测 输出电压 并调节电流源 根据负载的需求 以把输 出电压保持在期望的数值 电流源的设计极限限定了稳压器在仍然
  • C++输入输出(一)

    C 并没有专门的输入输出函数 他们都存在于库中 如果要使用cout cin和getline 需要导入iostream库 如果要是用其他的输入输出方式 需要导入cstdio库 一 cout流输出 这个输出方式我们很早就学过了 他的使用方式如下
  • Home Assistant 南方电网 计算电费

    目录 1 China Southern Power Grid Statistics集成 2 获取当月用电情况 3 计算电费然后在UI上显示 3 效果 1 China Southern Power Grid Statistics集成 链接 2
  • ANSYS WORKBENCH 后处理 之 提取截面查看云图

    这是一个结果的云图 现在想要查看管道某横截面的云图 步骤1右键coordinate systems 创建一个坐标系步骤2更改新建坐标轴属性 步骤3新建一个surface 定义中选择刚才创建的坐标系步骤4右键solution 选择刚才创建的面
  • c++的char[]和char*的区别

    大家先来看这道测试题 char str1 abc char str2 abc const char str3 abc const char str4 abc const char str5 abc const char str6 abc c
  • docker命令自动补全

    很多命令都会提供一个bash complete的脚本 在执行该命令时 敲tab可以自动补全参数 会极大提高生产效率 docker亦如此 如 yum install docker后 会有一个文件 usr share bash completi
  • Linux搭建gitlab以及汉化

    注 请使用管理员权限的用户 执行如下操作 文章目录 GitLab搭建 一 安装并配置必要的依赖关系 1 安装ssh 3 启动SSH服务 4 安装防火墙 如果已经安装了防火墙并且已经在运行状态 则可直接进行第6步 5 开启防火墙 6 添加ht
  • 【OpenGL学习】Shader和Shader类的抽象

    Shader 本节学习OpenGL中Shader的使用并将其抽象为类 简要介绍OpenGL所使用的着色器语言GLSL 一 什么是Shader 参考维基百科中对Shader的定义 着色器 维基百科 自由的百科全书 wikipedia org
  • 【终极版】java连接oracle数据库三种方式(上篇)

    很多小伙伴都对java连接oracle数据库的操作弄的稀里糊涂 今天我就贴出终极版 一举解决所有的连接方式 上篇主要是解决利用驱动连接的方式 我是小順 请大家关注我 我会给大家发更多的工具 JAR包 import java sql Conn
  • Mac 电脑python 升级3.7版本

    转自 https www jianshu com p 5f55997ab719 官网下载python3 7 并且安装https www python org downloads mac osx 本人电脑有多个版本的python 为了体验新版
  • ffmpeg推流参考文章

    https www cnblogs com leisure chn p 10623968 html https www bilibili com read cv12294853 基于M3568平台移植nginx https z zlg cn
  • Docker笔记:基本概念、镜像、容器、仓库以及数据卷的使用

    什么是docker docker 是一个开源的应用容器引擎 可以使用docker将应用程序和依赖打包到一个镜像之中 可以非常方便的移植到其他机器上运行 使用docker构建打包我们的应用 build 之后可以像集装箱一样很方便的传输到别的机
  • 【Learning PGM in R】第一章 概率推理

    目录 1 1机器学习 1 1 1监督学习 1 1 2无监督学习和强化学习 1 2概率表示 1 2 1概率计算和随机变量 1 2 2条件概率 联合概率分布和边缘分布 1 3贝叶斯规则 1 4概率图模型基础 1 4 1概率图模型基础理论 1 4
  • 使用Kalman滤波器做目标跟踪

    https www mathworks com help vision examples using kalman filter for object tracking html 由该例整理而来 1 前言 2 介绍 3 目标跟踪的挑战 4
  • Vue2屎山代码大盘点

    前言 相比其他的框架来说 Vue中更容易产出屎山代码 因为Vue中的options就是一个大对象 导致js本身的很多检测都失效了 比如一个函数没有用到的话会 变灰 template中代码提示比较少 较多的mixins等等 遇到屎山代码 大多