前端代码规范
前言
良好的代码规范有利于提高项目开发效率以及减少阅读代码的困难,本规范结合了(chaoxi)多个流行的代码规范以及前人的开发经验而成,参考规范进行开发提高代码质量
HTML 规范
设置标准模式的文档类型
1 |
|
设置页面语言
1 | <html lang="zh-CN"></html> |
设置页面字符编码
1 | <meta charset="UTF-8" /> |
使用语义化的标签准确地描述网页的内容
1 | <main> |
确保页面可访问性
- 给
img
标签添加正确的alt
属性 - 使用
label
标签对表单进行控制
使用字符实体替代特殊字符
1 | <span>></span> |
使用两个空格缩进
1 | <section> |
按特定顺序书写标签属性
class
id
,name
data-*
src
,for
,type
,href
,value
title
,alt
role
,aria-*
1 | <!-- 示例 --> |
不对布尔属性赋值
1 | <!-- 示例 --> |
CSS 规范
全局设置盒子模型
1 | * { |
使用简洁的 class 命名
class 的命名应该尽量简洁、明确,以字母开头命名,且全部字母为小写,单词之间使用连字符 “-” 连接。
每个模块使用一个模块命名,子元素使用模块名 + 元素作用名名
1 | <!-- 示例 --> |
使用常用的 class 命名
包裹类: container, wrapper, outer, inner, box, header, footer, main, content, aside, page, section, block
状态类: primary, secondary, success, danger, warning, info, error, link, light, dark, disabled, active, checked, loading
尺寸类: large, middle, small, bigger, smaller
组件类: card, list, picture, carousel, swiper, menu, navs, badge, hint, modal, dialog
位置类: first, last, current, prev, next, forward, back
文本类: title, desc, content, date, author, category,label,tag
人物类: avatar, name, age, post, intro
Class Name | 含义 |
---|---|
about | 关于 |
account | 账户 |
arrow | 箭头图标 |
article | 文章 |
aside | 边栏 |
audio | 音频 |
avatar | 头像 |
bg,background | 背景 |
bar | 栏(工具类) |
branding | 品牌化 |
crumb,breadcrumbs | 面包屑 |
btn,button | 按钮 |
caption | 标题,说明 |
category | 分类 |
chart | 图表 |
clearfix | 清除浮动 |
close | 关闭 |
col,column | 列 |
comment | 评论 |
community | 社区 |
container | 容器 |
content | 内容 |
copyright | 版权 |
current | 当前态,选中态 |
default | 默认 |
description | 描述 |
details | 细节 |
disabled | 不可用 |
entry | 文章,博文 |
error | 错误 |
even | 偶数,常用于多行列表或表格中 |
fail | 失败(提示) |
feature | 专题 |
fewer | 收起 |
field | 用于表单的输入区域 |
figure | 图 |
filter | 筛选 |
first | 第一个,常用于列表中 |
footer | 页脚 |
forum | 论坛 |
gallery | 画廊 |
group | 模块,清除浮动 |
header | 页头 |
help | 帮助 |
hide | 隐藏 |
hightlight | 高亮 |
home | 主页 |
icon | 图标 |
info,information | 信息 |
last | 最后一个,常用于列表中 |
links | 链接 |
login | 登录 |
logout | 退出 |
logo | 标志 |
main | 主体 |
menu | 菜单 |
meta | 作者、更新时间等信息栏,一般位于标题之下 |
module | 模块 |
more | 更多(展开) |
msg,message | 消息 |
nav,navigation | 导航 |
next | 下一页 |
nub | 小块 |
odd | 奇数,常用于多行列表或表格中 |
off | 鼠标离开 |
on | 鼠标移过 |
output | 输出 |
pagination | 分页 |
pop,popup | 弹窗 |
preview | 预览 |
previous | 上一页 |
primary | 主要 |
progress | 进度条 |
promotion | 促销 |
rcommd,recommendations | 推荐 |
reg,register | 注册 |
save | 保存 |
search | 搜索 |
secondary | 次要 |
section | 区块 |
selected | 已选 |
share | 分享 |
show | 显示 |
sidebar | 边栏,侧栏 |
slide | 幻灯片,图片切换 |
sort | 排序 |
sub | 次级的,子级的 |
submit | 提交 |
subscribe | 订阅 |
subtitle | 副标题 |
success | 成功(提示) |
summary | 摘要 |
tab | 标签页 |
table | 表格 |
txt,text | 文本 |
thumbnail | 缩略图 |
time | 时间 |
tips | 提示 |
title | 标题 |
video | 视频 |
wrap | 容器,包,一般用于最外层 |
wrapper | 容器,包,一般用于最外层 |
不使用 ID 选择器
1 | // bad |
不要为 0
值设置单位
1 | // bad |
遵循以下的样式书写顺序
- 布局定位属性:position / display / float / clear / visibility / overflow
- 盒属性:width / height / margin / padding / border / background
- 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
- 视觉属性:background-color / border / border-radius / box-shadow
- 其他属性:content / cursor / text-shadow / background:linear-gradient
1 | .box { |
嵌套选择器的深度不要超过 3 层
1 | .container { |
不要使用 @import
1 | /* bad */ @import url("other.css"); /* good */ |
将媒体查询语句放在靠近相关规则最近的位置
1 | .element { |
使用简短的申明语句
1 | // bad |
使用 stylelint 检查样式代码
https://github.com/shinnn/vscode-stylelint
JS 规范
使用 const 优于 let,弃用 var
1 | // bad |
使用字面量创建对象
1 | // bad |
函数名或方法名使用动宾短语
1 | // bad |
命名所有的方法包含闭包和回调, 避免匿名方法
命名方法和函数可以让你在代码运行出错时更快的找到错误
布尔值变量使用 is 开头的词组
1 | // bad |
避免重复的描述对象
1 | // bad |
使用有意义可读性好的变量名
1 | // bad |
将函数参数限制 2 个以内
1 | // bad |
封装判断条件
将多个条件的判断结果赋值给一个变量或使用一个函数返回
1 | // bad |
避免否定情况的判断
尽可能只使用正向的判断
1 | // bad |
删除无效的代码
及时删除不再被调用的代码,避免给阅读代码带来困扰
使用 try/catch
语句捕获可能出现的错误
1 | try { |
只注释业务逻辑复杂性的代码
1 | function hashIt(data) { |
Vue 规范
将组件名命名为多个单词
1 | // bad |
使用 PascalCase 或者 kebab-case 命名组件
1 | <!-- bad --> |
详细定义组件的 Prop
1 | // bad |
在 v-for 循环上加 key
1 | <!-- bad --> |
不要把 v-if 和 v-for 同时用在同一个元素上
1 | <!-- bad --> |
为组件样式设置作用域
1 | <!-- bad --> |
组件和实例的选项使用统一的顺序
- 副作用(触发组件外的影响)
el
- 全局感知(要求组件以外的知识)
name
parent
- 组件类型(更改组件的类型)
functional
- 模板修改器(改变模板的编译方式)
delimiters
comments
- 模板依赖(模板内使用的资源)
components
directives
filters
- 组合(向选项里合并属性)
extends
mixins
- 接口(组件的接口)
inheritAttrs
model
props
/propsData
- 本地状态(本地的响应式属性)
data
computed
- 事件(通过响应式事件触发的回调)
watch
- 生命周期钩子 (按照它们被调用的顺序)
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
activated
deactivated
beforeDestroy
destroyed
- 非响应式的属性(不依赖响应系统的实例属性)
methods
- 渲染(组件输出的声明式描述)
template
/render
renderError
元素和组件的特性使用统一的顺序
- 定义(提供组件的选项)
is
- 列表渲染(创建多个变化的相同元素)
v-for
- 条件渲染(元素是否渲染/显示)
v-if
v-else-if
v-else
v-show
v-cloak
- 渲染方式(改变元素的渲染方式)
v-pre
v-once
- 全局感知(需要超越组件的知识)
id
- 唯一的特性(需要唯一值的特性)
ref
key
slot
- 双向绑定(把绑定和事件结合起来)
v-model
- 其它特性 (所有普通的绑定或未绑定的特性)
- 事件(组件事件监听器)
v-on
- 内容(覆写元素的内容)
v-html
v-text
保证一个组件专注于解决一个问题
确保一个组件是独立的、可复用的、微小的和可测试的
将行内表达式转为 computed
1 | // bad |
尽可能使用 mixins
Mixins 封装可重用的代码,避免了重复。如果两个组件共享有相同的功能,则可以使用 mixin
1 | const HelloMixin = { |
Node 规范
require 文件夹,而不是文件
在一个文件夹中开发库/模块,放置一个文件 index.js 暴露模块的内部
使用 .npmrc 锁住依赖版本
代码必须在所有的环境中是相同的,但是 Npm 默认情况下会拿包的最新版本,配置 .npmrc 锁定依赖版本
1 | save-exact=true |
在 Node 外管理前端资源
使用专门的中间件(nginx,S3,CDN)服务前端内容,这是因为在处理大量静态文件的时候,由于 node 的单线程模型,它的性能很受影响
使用中间件限制并发请求
DOS 攻击非常流行而且相对容易处理。使用外部服务,比如 cloud 负载均衡, cloud 防火墙, nginx, 或者(对于小的,不是那么重要的 app)一个速率限制中间件(比如express-rate-limit),来实现速率限制。否则应用程序可能受到攻击, 导致拒绝服务, 在这种情况下, 真实用户会遭受服务降级或不可用。
验证传入的 JSON schemas
验证传入请求的 body payload,并确保其符合预期要求, 如果没有, 则快速报错。为了避免每个路由中繁琐的验证编码, 您可以使用基于 JSON 的轻量级验证架构,比如 jsonschema or joi,否则您疏忽和宽松的方法大大增加了攻击面, 并鼓励攻击者尝试许多输入, 直到他们找到一些组合, 使应用程序崩溃。
使用非 root 用户运行 Node.js
Node.js 作为一个具有无限权限的 root 用户运行,这是一种普遍的情景。例如,在 Docker 容器中,这是默认行为。建议创建一个非 root 用户,并保存到 Docker 镜像中(下面给出了示例),或者通过调用带有”-u username” 的容器来代表此用户运行该进程,否则在服务器上运行脚本的攻击者在本地计算机上获得无限制的权利 (例如,改变 iptable,引流到他的服务器上)
其它规范
使用 jest 进行单元测试
通常只要求对一些基础/底层的组件、函数进行测试, 视情况考虑是否要测试业务代码
使用 Prettier 格式化代码
所有代码格式相关的工作都可以交给 Prettier 来做
合理的图片命名
图片业务 + 图片功能类别 + 图片模块名称 + 图片精度