Vue2屎山代码大盘点

前言

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

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

文章目录

  • 一号屎山--目录杂乱
  • 二号屎山--奇葩命名法
  • 三号屎山--组件不拆分
  • 四号屎山--复杂的表达式
  • 五号屎山--大量重复节点
  • 六号屎山--if else switch
  • 七号屎山--后端参数处理
  • 八号屎山--硬编码
  • 九号屎山--Mixins屎山
  • 十号屎山--无用代码不删除
  • 十一号屎山--类名无规范
  • 十二号屎山--样式大量重复
  • 十三号屎山--不写注释
  • 十四号屎山--组件不写name

一号屎山–目录杂乱

危害程度:⭐️

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屎山。

四号屎山–复杂的表达式

危害程度:⭐️⭐️⭐️

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

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

  <divclass="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里面包含了几十行代码的时候,就会发现这里面的重复元素太多了,进而无法维护;

六号屎山–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,目录中同时存在这两个文件,让人摸不着头脑,无形增加了项目复杂度,试想一下如果一个超大项目,一半的文件都是没有引用到的,那是多么的可怕!

十一号屎山–类名无规范

危害程度:⭐️

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

#id{}
#App{}
.AppBuy{}
.app-buy{}
.app_buy{}
.App_Buy{}

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

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

危害程度:⭐️

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

十三号屎山–不写注释

危害程度:⭐️⭐️⭐️⭐️⭐️
写个注释是举手之劳,花不了多少时间,而且前面所有的屎山堆起来,如果有注释的话还是可以快速理解其含义的,但是如果再加上不写注释,那就是天坑了,谁也救不了这个屎山;
罗马的道路不是一日铺成的,屎山的代码也不是一天写成的,而是在每个开发者无所谓的心态下堆成的,如果平时多注意注意至少也能保证自己写的代码”留有余香“。
建议读完本文之后再读一读参考文章,最后是严格地执行!如果以时间不够为借口而不执行那么看再多的文章也没有用!

十四号屎山–组件不写name

危害程度:⭐️

// 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,组件名也是固定的,另外推荐组件名与文件名一致,这样大大地降低了组件搜索成本;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/76532.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mobaXterm使用pycharm

首先去pycharm的官网PyCharm: the Python IDE for Professional Developers by JetBrains 下载pycharm&#xff08;选择linux的community版本即可&#xff09; 下载后的压缩包拖拽到mobaXterm如下位置&#xff1a; 进入压缩包所在的文件夹&#xff08;图中这个位置是root目录&…

记一次线程堵塞(挂起)导致消息队列积压

1 背景 A服务作为生产者&#xff0c;每天发送上千万的mq消息&#xff0c;每一个消息包含500个用户ids数据。B服务作为消费者&#xff0c;接受MQ消息并通过http调用第三方请求进行业务处理&#xff0c;消费组启用了rabbitmq的多线程消费组&#xff0c;一个实例并发40个mq消费者…

Git Cherry Pick命令

1. 简介 Git是一款分布式版本控制系统&#xff0c;它提供了许多强大的功能来管理代码的版本和变更。其中之一就是cherry-pick命令&#xff0c;它允许我们选择某个分支上的一个或多个提交&#xff0c;并将它们应用到当前分支上。这个功能非常有用&#xff0c;可以帮助我们在不合…

Python文件操作(02):读文件

一、读文本文件 打开文件读文件内容关闭文件 1、在读取文件内容后进行解码操作 """ 1. 打开文件- 路径&#xff1a;相对路径&#xff1a;当前项目&#xff08;读文件.py&#xff09;所在的目录下查找需要读取的文件绝对路径&#xff1a;文件--右键--Copy Pat…

Java中的Maven是什么?

Maven是一个开源的项目管理和构建工具&#xff0c;用于Java项目的构建、依赖管理和项目信息管理。它提供了一种标准的项目结构、规范的构建过程和丰富的插件生态系统&#xff0c;简化了项目的管理和构建过程。 Maven基于项目对象模型&#xff08;Project Object Model&#xf…

四、Go中的条件判断和for循环

一、if条件判断 代码&#xff1a; package mainimport "fmt"func main() {//if 条件判断score : 50judgingGrades(score)}/* * go语言中 if的用法 */ func judgingGrades(score int) {if score > 90 {fmt.Println("优等生")} else if score > 80 |…

Prompt Tuning训练过程

目录 0. 入门 0.1. NLP发展的四个阶段&#xff1a; Prompt工程如此强大&#xff0c;我们还需要模型训练吗&#xff1f; - 知乎 Prompt learning系列之prompt engineering(二) 离散型prompt自动构建 Prompt learning系列之训练策略篇 - 知乎 ptuning v2 的 chatglm垂直领域训练记…

读高性能MySQL(第4版)笔记05_优化服务器设置

1. 除非遇到异常情况&#xff0c;否则不需要调整配置 1.1. 不要“调优”服务器&#xff0c;不要使用比率、公式或“调优脚本”作为设置配置变量的基础 1.1.1. 在互联网上搜索配置建议并不总是一个好主意&#xff0c;你会在博客、论坛等找到很多糟糕的建议 1.1.2. 很难判断谁…

Python机器学习、深度学习在气象、海洋、水文领域实践应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;能够在不同操作系统和平台使用&#xff0c;简洁的语法和解释性语言使其成为理想的脚本语言。除了标准库&#xff0c;还有丰富的第三方库&#xff0c;Python在数据处理、科学计算、数学建模、数据挖…

SpringBoot+Vue 整合websocket实现简单聊天窗口

效果图 1 输入临时名字充当账号使用 2 进入聊天窗口 3 发送消息 &#xff08;复制一个页面&#xff0c;输入其他名字&#xff0c;方便展示效果&#xff09; 4 其他窗口效果 代码实现 后端SpringBoot项目&#xff0c;自行创建 pom依赖 <dependency><groupId…

uni-app 使用uCharts-进行图表展示(折线图带单位)

前言 在uni-app经常是需要进行数据展示&#xff0c;针对这个情况也是有人开发好了第三方包&#xff0c;来兼容不同平台展示 uCharts和pc端的Echarts使用差不多&#xff0c;甚至会感觉在uni-app使用uCharts更轻便&#xff0c;更舒服 但是这个第三方包有优点就会有缺点&#xf…

vue 部署到本机IIS 部署 SPA 应用

安装 URL Rewrite Works With: IIS 7, IIS 7.5, IIS 8, IIS 8.5, IIS 10 URL Rewrite : The Official Microsoft IIS Site 目前电脑IIS是6版本的&#xff0c;以下的方法不太合适操作。目前用Nginx部署&#xff0c;够用了。 nginx配置参考&#xff1a; uni-app 前面项目&am…

Segment Anything Model(SAM)论文解读

一、引言 在这项工作中&#xff0c;作者的目标是建立一个图像分割的基础模型。也就是说&#xff0c;寻求开发一个提示模型&#xff0c;并使用一个能够实现强大泛化的任务在广泛的数据集上对其进行预训练。有了这个模型&#xff0c;使用即时工程解决新数据分布上的一系列下游分…

【rpc】Dubbo和Zookeeper结合使用,它们的作用与联系(通俗易懂,一文理解)

目录 Dubbo是什么&#xff1f; 把系统模块变成分布式&#xff0c;有哪些好处&#xff0c;本来能在一台机子上运行&#xff0c;为什么还要远程调用 Zookeeper是什么&#xff1f; 它们进行配合使用时&#xff0c;之间的关系 服务注册 服务发现 动态地址管理 Dubbo是…

Nacos docker实现nacos高可用集群项目

目录 Nacos是什么&#xff1f; Nacos在公司里的运用是什么&#xff1f; 使用docker构建nacos容器高可用集群 实验规划图&#xff1a;​编辑 1、拉取nacos镜像 2、创建docker网桥&#xff08;实现集群内的机器的互联互通&#xff08;所有的nacos和mysql&#xff09;&#x…

环境变量与Path环境变量

“环境变量”和“path环境变量”其实是两个东西&#xff0c;这一点大家一定要区分开&#xff0c;不要混为一谈。 “环境变量”是操作系统工作环境设置的一些选项或属性参数。每个环境变量由变量名和文件路径组成的&#xff0c;可以设置很多个环境变量。 我们一般使用环境变量…

冒泡排序、选择排序、插入排序、希尔排序

冒泡排序 基本思想 代码实现 # 冒泡排序 def bubble_sort(arr):length len(arr) - 1for i in range(length):flag Truefor j in range(length - i):if arr[j] > arr[j 1]:temp arr[j]arr[j] arr[j 1]arr[j 1] tempflag Falseprint(f第{i 1}趟的排序结果为&#…

人生中第一次向开源项目提交PR记录

git了解很久了&#xff0c;但是就是没有向大一点的项目提交过pr&#xff0c;都是自己瞎折腾&#xff0c;记录一下开源项目提交PR过程&#xff0c;省略的过程可以参考&#xff1a; https://www.runoob.com/git/git-tutorial.html&#xff0c;这个里面包括安装&#xff0c;使用&a…

正规好用的电脑端抽奖软件有哪些?

这几个软件都是本人反复用过、反复比较的&#xff0c;且都超过5年。 1. 518抽奖软件 518抽奖软件&#xff0c;518我要发&#xff0c;超好用的年会抽奖软件&#xff0c;简约设计风格。 包含文字号码抽奖、照片抽奖两种模式&#xff0c;支持姓名抽奖、号码抽奖、数字抽奖、照片抽…

如何进行错误处理和异常处理?

错误处理和异常处理是编程中非常重要的概念&#xff0c;它们允许我们在程序运行时处理各种问题和异常情况&#xff0c;以确保程序的稳定性和可靠性。在C语言中&#xff0c;错误处理和异常处理通常通过条件语句和函数来实现。本文将详细讨论C语言中的错误处理和异常处理的方法&a…