市面上常用的命名规范:
camelCase
(小驼峰式命名法 —— 首字母小写)PascalCase
(大驼峰式命名法 —— 首字母大写)kebab-case
(短横线连接式)Snake
(下划线连接式)全部采用小写方式, 以短横线分隔。
mall-management-system
mall_management-system / mallManagementSystem
参照项目命名规则,有复数结构时,要采用复数命名法。
docs、assets、images、icons、components、directives、enums、hooks、utils、views
script / style / demo_scripts / demoStyles
1.VUE
的项目中的组件components
中的组件使用 PascalCase
命名
HeadSearch / PageLoading / Authorized / NoticeIcon
headSearch / page-loading
2. VUE
的项目中的页面目录使用 camelCase
命名
pageOne / shoppingCar / userManagement
shopping-car / UserManagement
Snake
方式全部采用Snake
命名方式, 优先选择单个单词命名,多个单词命名以下划线连接。
banner_sina.gif
menu_aboutus.gif
menutitle_news.gif
logo_police.gif
logo_national.gif
pic_people.jpg
pic_TV.jpg
HTML
文件名: camelCase
方式优先选择单个单词命名,多个单词命名以camelCase
方式。
|- errorReport.html
|- successReport.html
CSS
文件名: camelCase
方式全部采用camelCase
方式, 优先选择单个单词命名,多个单词命名以短横线分隔。
|- index.scss
|- userCenter.scss
JavaScript
文件名: camelCase
方式全部采用camelCase
写方式,优先选择单个单词命名,多个单词命名以短横线分隔。
|- index.js
|- util.js
|- userCenter.js
TypeScript
文件名: camelCase
方式全部采用camelCase
写方式,优先选择单个单词命名,多个单词命名以短横线分隔。
|- index.ts
|- util.ts
|- userCenter.ts
除特定配置文件和依赖除外
Vue
组件名文件扩展名为 .vue
的 single-file components
(单文件组件)。单文件组件名应该PascalCase
方式。
components/
|- MyComponent.vue
和父组件紧密耦合的子组件应该以父组件名作为前缀命名。 因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。
components/
|- RoleList.vue
|- RoleListItem.vue
|- RoleListItemButton.vue
组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾。 因为编辑器通常会按字母顺序组织文件,所以现在组件之间的重要关系一目了然。如下组件主要是用于搜索和设置功能。
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue
组件名应该倾向于完整而不是缩写。 编辑器中的自动补全已经让书写长命名的代价非常之低了,而其带来的明确性却是非常宝贵的。不常用的缩写尤其应该避免。
components/
|- StudentDashboardSettings.vue
|- RoleAuthorization.vue
**全局组件应采用文件夹加index.vue
格式。文件夹名称采用PascalCase
格式命名。**其内部组件和页面内部组件采取组件规范。
全局组件
components/
|- ProTable
| |- index.vue
| |- components/
| | |- ProTableHeader.vue
| | |- ProTableBody.vue
api
文件api
目录Role
模块// api目录
api/modules/role.ts:
// 添加角色
addRole: (data) => {
return postAxios('/role/add', data)
},
// 删除角色
deleteRole: (roleId) => {
return postAxios('/role/delete/' + roleId)
},
Vue3
项目文件资源目录示例:my-project-name/
├─ .husky # husky 配置文件
├─ .vscode # VSCode 推荐配置
├─ build # Vite 配置项
├─ public # 静态资源文件
├─ docs # 项目的细化文档目录(可选)
├─ node_modules # 下载的依赖包
├─ src # 源码目录
│ ├─ api # http 请求目录
│ │ ├─ config # http 配置项
│ │ ├─ helper # http 封装
│ │ ├─ interface # http 接口类型
│ │ │ ├─ userCenter.ts # http 用户接口
│ │ ├─ modules # http 接口模块
│ │ │ ├─ userCenter.ts # http 用户api模块
│ │ └─ index.ts # http 请求入口
│ ├─ assets # 静态资源目录
│ ├─ components # 全局组件
│ │ ├─ ProTable # ProTable组件文件夹
│ │ │ ├─ index.vue # ProTable组件
│ │ │ ├─ interface # ProTable公共接口
│ │ │ │ ├─ index.ts # ProTable公共接口文件
│ │ │ ├─ components # ProTable内部组件
│ │ │ │ ├─ Pagination.vue # ProTable内部分页组件
│ │ │ │ ├─ TableColumn.vue # ProTable内部列组件
│ ├─ config # 全局配置项
│ ├─ constants # 全局常量
│ ├─ enums # 项目常用枚举
│ ├─ hooks # 常用 Hooks 封装
│ ├─ languages # 语言国际化 i18n
│ ├─ directives # 全局指令文件
│ ├─ mockApi # 模拟接口,临时存放
│ ├─ mockData # 模拟数据,临时存放
│ ├─ plugins # 插件
│ ├─ routers # 路由管理
│ ├─ stores # pinia store
│ ├─ styles # 全局样式文件
│ ├─ utils # 常用工具库
│ ├─ views # 页面存放目录
│ │ ├─ role # role模块名
│ │ │ ├─ userRole # 用户role
│ │ │ │ ├─ index.vue # 用户role首页/列表
│ │ │ │ ├─ index.scss # 用户role css
│ │ │ │ └─ detail.vue # role详情页面
│ │ │ ├─ systemRole # 系统role
│ │ │ ├─ components # role模块通用组件文件夹
│ │ │ │ └─ RoleAuthorization.vue # role授权组件
│ │ │ └─ interface # role公共接口文件夹
│ │ └─ user # user模块名
│ ├─ App.vue # 项目根组件
│ ├─ main.ts # 入口文件
│ └─ vite-env.d.ts # 指定 ts 识别 vue
├─ .editorconfig # 统一不同编辑器的编码风格
├─ .env # vite 常用配置
├─ .env.development # 开发环境配置
├─ .env.production # 生产环境配置
├─ .env.test # 测试环境配置
├─ .eslintignore # 忽略 Eslint 校验
├─ .eslintrc.cjs # Eslint 校验配置文件
├─ .gitignore # 忽略 git 提交
├─ .prettierignore # 忽略 Prettier 格式化
├─ .prettierrc.cjs # Prettier 格式化配置
├─ .stylelintignore # 忽略 stylelint 格式化
├─ .stylelintrc.cjs # stylelint 样式格式化配置
├─ CHANGELOG.md # 项目更新日志
├─ commitlint.config.cjs # git 提交规范配置
├─ index.html # 入口 html
├─ LICENSE # 开源协议文件
├─ lint-staged.config.cjs # lint-staged 配置文件
├─ package-lock.json # 依赖包包版本锁
├─ package.json # 依赖包管理
├─ postcss.config.cjs # postcss 配置
├─ README.md # README 介绍
├─ tsconfig.json # typescript 全局配置
└─ vite.config.ts # vite 全局配置文件
name
组件名应该始终是多个单词,应该始终是 PascalCase
的。 根组件 App
以及
之类的 Vue
内置组件除外。
prop
在声明 prop
的时候,其命名应该始终使用 camelCase
,而在模板和 JSX
中应该始终使用 kebab-case
。我们单纯的遵循每个语言的约定,在 JavaScript
中更自然的是 camelCase
。而在 HTML
中则是 kebab-case
。
router
**Vue Router Path
命名采用 camelCase
格式。**和views
页面尽量保持一致。
// good
{
"path": "/proTable",
"name": "proTable",
"redirect": "/proTable/useProTable",
"meta": {
"icon": "MessageBox",
},
"children": [
{
"path": "/proTable/useProTable",
"name": "useProTable",
"component": "/proTable/useProTable/index",
"meta": {
"icon": "Menu",
}
]
},
// bad
{
path: '/user_info', // user_info 当成一个单词
name: 'UserInfo',
meta: {
title: ' - 用户',
desc: ''
},
component: () => import('@/views/file/user-Info.vue')
},
path除了采用camelCase
命名规范以外,必须以 /
开头,即使是children
里的path
也要以 /
开头
目的:
经常有这样的场景:某个页面有问题,要立刻找到这个vue
文件,如果不用以/
开头,path
为parent
和children
组成的,可能经常需要在router
文件里搜索多次才能找到,而如果以/
开头,则能立刻搜索到对应的组件
对于绝大多数项目来说,在 单文件组件 和 字符串模板 中 组件名 应该总是 PascalCase
的 ,
但是在 DOM
模板中总是 kebab-case
的。
camelCase
// good
let tableTitle = "LoginTable"
let mySchool = "我的学校"
// bad
var getTitle = "LoginTable"
const MAX_COUNT = 10
const URL = 'http://test.host.com'
camelCase
// 1、普通情况下,使用动词 + 名词形式
// good
jumpPage、openCarInfoDialog
// bad
go、nextPage、show、open、login
// 2、请求数据方法,以 data 结尾
// good
getListData、postFormData
// bad
takeData、confirmData、getList、postForm
// 3、单个动词的情况
init、refresh
动词 | 含义 | 返回值 |
---|---|---|
can |
判断是否可执行某个动作 (权 ) | 函数返回一个布尔值。true :可执行;false :不可执行; |
has |
判断是否含有某个值 | 函数返回一个布尔值。true:含有此值;false:不含有此值; |
is |
判断是否为某个值 | 函数返回一个布尔值。true:为某个值;false:不为某个值; |
get |
获取某个值 | 函数返回一个非布尔值 |
set |
设置某个值 | 无返回值、返回是否设置成功或者返回链式对象 |
附: 函数方法常用的动词:
get 获取/set 设置,
add 增加/remove 删除
create 创建/destory 移除
start 启动/stop 停止
open 打开/close 关闭,
read 读取/write
load 写入/save 保存,
create 创建/destroy 销毁
begin 开始/end 结束,
backup 备份/restore 恢复,
import 导入/export 导出,
split 分割/merge 合并,
inject 注入/extract 提取,
attach 附着/detach 脱离,
bind 绑定/separate 分离,
view 查看/browse 浏览,
edit 编辑/modify 修改,
select 选取/mark 标记,
copy 复制/paste 粘贴,
undo 撤销/redo 重做,
insert 插入/delete 移除,
add 加入/append 添加,
clean 清理/clear 清除,
index 索引/sort 排序,
find 查找/search 搜索,
increase 增加/decrease 减少,
play 播放/pause 暂停,
launch 启动/run 运行,
compile 编译/execute 执行,
debug 调试/trace 跟踪,
observe 观察/listen 监听,
build 构建/publish 发布,
input 输入/output 输出,
encode 编码/decode 解码,
encrypt 加密/decrypt 解密,
compress 压缩/decompress 解压缩,
pack 打包/unpack 解包,
parse 解析/emit 生成,
connect 连接/disconnect 断开,
send 发送/receive 接收,
download 下载/upload 上传,
refresh 刷新/synchronize 同步,
update 更新/revert 复原,
lock 锁定/unlock 解锁,
check out 签出/check in 签入,
submit 提交/commit 交付,
push 推/pull 拉,
expand 展开/collapse 折叠,
begin 起始/end 结束,
start 开始/finish 完成,
enter 进入/exit 退出,
abort 放弃/quit 离开,
obsolete 废弃/depreciate 废旧,
collect 收集/aggregate 聚集
自定义事件应始终使用 kebab-case
的事件名。
不同于组件和 prop
,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。
// 父组件中调用
camelCase
handle
+ 名称(可选)+ 动词
api
命名变量命名要与尽可能与模块保持一致,写好注释。
// 添加角色
addRole: (data) => {
return postAxios('/role/add', data)
},
// 删除角色
deleteRole: (roleId) => {
return postAxios('/role/delete/' + roleId)
},
TS
接口命名PascalCase
命名。不要使用I
做为接口名前缀。接口成员使用 camelCase
方式命名// Good
interface Foo {
bar: number;
baz(): number;
}
// Bad
interface IFoo {
Bar: number;
Baz(): number;
}
PascalCase
命名。// 推荐
enum StatusEnum {
SUCCESS = 'success'
}
// Good
enum StatusEnum {
Success = 'success'
}
// Bad
enum Status {
success = 'success'
}
Vue
script
标签内部加上name
属性, 用于定义组件名称script
标签内部结构顺序:
import
引入顺序
props
示例:
data
ref
ref、reactive
都可以reactive
,(form
表单数据推荐使用reactive
)
computed
应该把复杂计算属性分割为尽可能多的更简单的属性。 小的、专注的计算属性减少了信息使用时的假设性限制,所以需求变更时也用不着那么多重构了。
v-for
设置键值在组件上必须用 key
搭配 v-for
,以便维护内部组件及其子树的状态。
-
{{ todo.text }}
v-if
和 v-for
放在同一个元素上永远不要把 v-if
和 v-for
同时用在同一个元素上。因为这可能导致渲染逻辑变得复杂且难以预测。
Vue3
中: 当它们同时存在于一个节点上时,v-if
比 v-for
的优先级更高。这意味着 v-if
的条件将无法访问到 v-for
作用域内定义的变量别名:
{{ todo.name }}
在外先包装一层 再在其上使用
v-for
可以解决这个问题 (这也更加明显易读):
{{ todo.name }}
一般我们在两种常见的情况下会倾向于这样做:
v-for="user in users" v-if="user.isActive"
)。在这种情形下,请将 users
替换为一个计算属性 (比如 activeUsers
),让其返回过滤后的列表。
-
{{ user.name }}
const activeUsers = computed(() => users.filter(user => user.isActive))
v-for="user in users" v-if="shouldShowUsers"
)。这种情形下,请将v-if
移动至容器元素上 (比如 ul, ol
)。// good
-
{{ user.name }}
// bad
-
{{ user.name }}
attribute
的元素多个 attribute
的元素占满一行之后应该分多行撰写,每个 attribute
一行。
//good
<img
src="https://vuejs.org/images/logo.png"
alt="Vue Logo"
title="vue"
width="100"
height="100"
align="right"
loading="lazy">
<MyComponent foo="a" bar="b" baz="c"/>
//bad
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo" title="vue" width="100"
height="100" align="right" loading="lazy">
<MyComponent
foo="a"
bar="b"
baz="c"
/>
组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。
复杂表达式会让你的模板变得不那么声明式。我们应该尽量描述应该出现的是什么,而非如何计算那个值。而且计算属性和方法使得代码可以重用。
// good
// 在模板中
{{ normalizedFullName }}
// 复杂表达式已经移入一个计算属性
const normalizedFullName = computed(() => {
return fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
})
// bad
{{
fullName.split(' ').map((word) => {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}}
:
表示 v-bind:
@
表示 v-on:
#
表示 v-slot:
<input
:value="newTodoText"
:placeholder="newTodoInstructions">
<input
@input="onInput"
@focus="onFocus">
<template #header>
<h1>Here might be a page title</h1>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
<Child #default="params">
...
</Child>
HTML
HTML5
文件模板:
DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>HTML5标准模版title>
head>
<body>
body>
html>
移动端:
DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
<meta name="format-detection" content="telephone=no">
<title>移动端HTML模版title>
<link rel="dns-prefetch" href="">
<link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="http://srcPath/index.css">
head>
<body>
body>
html>
PC 端:
DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="keywords" content="your keywords">
<meta name="description" content="your description">
<meta name="author" content="author,email address">
<meta name="robots" content="index,follow">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="renderer" content="ie-stand">
<title>PC端HTML模版title>
<link rel="dns-prefetch" href="">
<link rel="stylesheet" href="css/index.css">
<link rel="stylesheet" href="http://srcPath/index.css">
head>
<body>
body>
html>
HTML 元素共有以下5种:
area、base、br、col、command、embed、hr、img、input、keygen、link、meta、param、source、track、wbr
script、style
RCDATA
元素:textarea、title
MathML
命名空间和 SVG
命名空间的元素HTML
允许的元素都称为常规元素为了能让浏览器更好的解析代码以及能让代码具有更好的可读性,有如下约定:
/
字符。
<div>
<h1>我是h1标题h1>
<p>我是一段文字,我有始有终,浏览器能正确解析p>
div>
<br data-tomark-pass>
<div>
<h1>我是h1标题h1>
<p>我是一段文字,我有始无终,浏览器亦能正确解析
div>
<br/>
元素嵌套规范,每个块状元素独立一行,内联元素可选。
<div>
<h1>h1>
<p>p>
div>
<p><span>span><span>span>p>
<div>
<h1>h1><p>p>
div>
<p>
<span>span>
<span>span>
p>
段落元素与标题元素只能嵌套内联元素。
<h1><span>span>h1>
<p><span>span><span>span>p>
<h1><div>div>h1>
<p><div>div><div>div>p>
样式文件必须写上 @charset
规则,并且一定要在样式文件的第一行首个字符位置开始写,编码名用 “UTF-8”
。
Vite
构建工具的编码设置通常是基于项目的配置文件和构建过程中的默认设置。在大多数情况下,Vite
默认使用UTF-8
编码,这是现代Web
开发中广泛使用的字符编码标准
@charset "UTF-8";
.demo {}
/* @charset规则不在文件首行首个字符开始 */
@charset "UTF-8";
.demo {}
/* @charset规则没有用小写 */
@CHARSET "UTF-8";
.demo {}
/* 无@charset规则 */
.demo {}
样式书写一般有两种:一种是紧凑格式 (Compact
),一种是展开格式(Expanded
)。
Expanded
).demo {
display: block;
width: 50px;
}
Compact
).demo { display: block; width: 50px;}
样式选择器,属性名,属性值关键字全部使用小写字母书写,属性字符串允许使用大小写。
.demo {
display: block;
}
.demo {
DISPLAY: BLOCK;
}
.demo {
width: 100%;
}
.demo{
width:100%;
}
.demo {
box-shadow: 1px 1px 1px #333, 2px 2px 2px #ccc;
}
.demo {
box-shadow: 1px 1px 1px #333,2px 2px 2px #ccc;
}
CSS
选择器或新声明开启新行。.demo, .demo_logo, .demo_hd {
color: #ff0;
}
.nav{
color: #fff;
}
.demo, .demo_logo, .demo_hd {
color: #ff0;
}.nav{
color: #fff;
}
rgb() rgba() hsl() hsla() rect()
中不需有空格,且取值不要带有不必要的 0
。.demo {
color: rgba(255,255,255,.5);
}
.demo {
color: rgba( 255, 255, 255, 0.5 );
}
.demo {
color: #ffffff;
}
.demo {
color: #fff;
}
0
指明单位。.demo {
margin: 0 10px;
}
.demo {
margin: 0px 10px;
}
CSS
属性值需要用到引号时,统一使用双引号。
.demo {
font-family: "Hiragino Sans GB";
}
.demo {
font-family: 'Hiragino Sans GB';
}
样式建议遵循以下顺序:
position、top、right、z-index
等box-sizing、display、float、width、height、margin、padding
等font、line-height、color、text-align
等cursor
background、border、border-radius、box-shadow
等opacity、transition、transform、animation
等.demo {
position,
top,
right,
bottom,
left,
z-index,
box-sizing,
display,
flex,
flex-align,
flex-basis,
flex-direction,
flex-wrap,
flex-flow,
flex-shrink,
flex-grow,
flex-order,
flex-pack,
align-content,
align-items,
align-self,
justify-content,
order,
float,
width,
min-width,
max-width,
height,
min-height,
max-height,
padding,
padding-top,
padding-right,
padding-bottom,
padding-left,
margin,
margin-top,
margin-right,
margin-bottom,
margin-left,
overflow,
overflow-x,
overflow-y,
-webkit-overflow-scrolling,
-ms-overflow-x,
-ms-overflow-y,
-ms-overflow-style,
columns,
column-count,
column-fill,
column-gap,
column-rule,
column-rule-width,
column-rule-style,
column-rule-color,
column-span,
column-width,
orphans,
widows,
clip,
clear,
font,
font-family,
font-size,
font-style,
font-weight,
font-variant,
font-size-adjust,
font-stretch,
font-effect,
font-emphasize,
font-emphasize-position,
font-emphasize-style,
font-smooth,
src,
hyphens,
line-height,
color,
text-align,
text-align-last,
text-emphasis,
text-emphasis-color,
text-emphasis-style,
text-emphasis-position,
text-decoration,
text-indent,
text-justify,
text-outline,
-ms-text-overflow,
text-overflow,
text-overflow-ellipsis,
text-overflow-mode,
text-shadow,
text-transform,
text-wrap,
-webkit-text-size-adjust,
-ms-text-size-adjust,
letter-spacing,
-ms-word-break,
word-break,
word-spacing,
-ms-word-wrap,
word-wrap,
overflow-wrap,
tab-size,
white-space,
vertical-align,
direction,
unicode-bidi,
list-style,
list-style-position,
list-style-type,
list-style-image,
pointer-events,
-ms-touch-action,
touch-action,
cursor,
visibility,
zoom,
table-layout,
empty-cells,
caption-side,
border-spacing,
border-collapse,
content,
quotes,
counter-reset,
counter-increment,
resize,
user-select,
nav-index,
nav-up,
nav-right,
nav-down,
nav-left,
background,
background-color,
background-image,
filter,
background-repeat,
background-attachment,
background-position,
background-position-x,
background-position-y,
background-clip,
background-origin,
background-size,
border,
border-color,
border-style,
border-width,
border-top,
border-top-color,
border-top-style,
border-top-width,
border-right,
border-right-color,
border-right-style,
border-right-width,
border-bottom,
border-bottom-color,
border-bottom-style,
border-bottom-width,
border-left,
border-left-color,
border-left-style,
border-left-width,
border-radius,
border-top-left-radius,
border-top-right-radius,
border-bottom-right-radius,
border-bottom-left-radius,
border-image,
border-image-source,
border-image-slice,
border-image-width,
border-image-outset,
border-image-repeat,
outline,
outline-width,
outline-style,
outline-color,
outline-offset,
box-shadow,
opacity,
-ms-interpolation-mode,
page-break-after,
page-break-before,
page-break-inside,
transition,
transition-delay,
transition-timing-function,
transition-duration,
transition-property,
transform,
transform-origin,
perspective,
appearance,
animation,
animation-name,
animation-duration,
animation-play-state,
animation-timing-function,
animation-delay,
animation-iteration-count,
animation-direction,
animation-fill-mode,
fill,
stroke
}
CSS3
浏览器私有前缀CSS3
浏览器私有前缀在前,标准前缀在后。
.demo {
-webkit-border-color: #ffffff;
-moz-border-color: #ffffff;
-o-border-color: #ffffff;
-ms-border-color: #ffffff;
border-color: #ffffff;
}
scss、less
等css
预处理语言代码组织
@import
@import "mixins/size.less";
@default-text-color: #ffffff;
.page {
width: 960px;
margin: 0 auto;
}
避免嵌套层级过多
将嵌套深度限制在3级。对于超过4级的嵌套,给予重新评估。这可以避免出现过于详实的
CSS
选择器。避免大量的嵌套规则。当可读性受到影响时,将之打断。推荐避免出现多于20行的嵌套规则出现
.main-title{
.demo{
...
}
}
.demo{
.title{
.name{
color:#fff
}
}
}
.main{
.demo{
.title{
.name{
color:#fff
}
}
}
}
JavaScript
在单行代码块中使用空格。
const a = () => true
if (condition) return;
function foo () {return true}
if (foo) {bar = 0}
在编程过程中,大括号风格与缩进风格紧密联系,用来描述大括号相对代码块位置的方法有很多。在 JavaScript
中,主要有三种风格,如下:
One True Brace Style
if (foo) {
bar()
} else {
baz()
}
Stroustrup
if (foo) {
bar()
}
else {
baz()
}
Allman
if (foo)
{
bar()
}
else
{
baz()
}
下列关键字后必须有大括号:if, else, for, while, do, switch, try, catch, finally, with。
,若是单行代码块,则不写大括号。
const condition = Math.random() > 0.5;
if (condition) {
return;
}
或者
if (condition) return;
if (condition) { return };
let foo = 1, bar = 2
let foo = 1,bar = 2
let foo = 1 , bar = 2
let foo = 1 ,bar = 2
let obj = { "foo": "haha" }
let obj = { "foo" : "haha" }
if (a) {
b()
}
function a () {}
if (a){
b()
}
function a (){}
function func (x) {
// ...
}
function func(x) {
// ...
}
func()
func ()
func
()
let sum = 1 + 2
let sum = 1+2
undefined
判断永远不要直接使用 undefined
进行变量判断;使用 typeof
和字符串'undefined'
对变量进行判断。
if (typeof person === 'undefined') {
...
}
if (person === undefined) {
...
}
超过 3 个的情况使用对象的方式进行传递。
const foo = args => {
const { a, b, c, d } = args;
console.log(a, b, c, d);
};
const foo = (a, b, c, d) => {
console.log(a, b, c, d);
};
条件判断能使用三目运算符和逻辑运算符解决的,就不要使用条件判断,但是谨记不要写太长的三目运算符。如果超过 3 层请抽成函数,并写清楚注释。
优先使用 ||
、 &&
运算符。
function createMicrobrewery(name) {
let breweryName = name || 'Hipster Brew Co.';
}
function createMicrobrewery(name) {
let breweryName;
if (name) {
breweryName = name;
} else {
breweryName = 'Hipster Brew Co.';
}
}
避免直接拼接字符串带来的代码可读性降低、易出现 bug
等问题。
const date = '2011-01-01';
const time = '12:00';
const fullTime = `${date} ${time}`;
const fullTime = date + ' ' + time;
注释的目的:
注释的原则:
As short as possible
)As long as necessary
)一般用于简单的描述,如某些状态描述、属性描述等。
注释内容前后各一个空格字符,注释位于要注释代码的上面,单独占一行。
<div>...div>
<div>...div>
<div>
...
div>
一般用于描述模块的名称以及模块开始与结束的位置。
注释内容前后各一个空格字符, 表示模块开始,
表示模块结束,模块与模块之间相隔一行。
<div class="mod_a">
...
div>
<div class="mod_b">
...
div>
<div class="mod_a">
...
div>
<div class="mod_b">
...
div>
当模块注释内再出现模块注释的时候,为了突出主要模块,嵌套模块不再使用。
而改用
注释写在模块结尾标签底部,单独一行。
<div class="mod_a">
<div class="mod_b">
...
div>
<div class="mod_c">
...
div>
div>
注释内容第一个字符和最后一个字符都是一个空格字符,单独占一行,行与行之间相隔一行。
/* Comment Text */
.demo {}
/* Comment Text */
.demo {}
/*Comment Text*/
.demo {
display: block;
}
.demo {
display: block;/*Comment Text*/
}
注释内容第一个字符和最后一个字符都是一个空格字符,/*
与 模块信息描述占一行,多个横线分隔符 -
与 */
占一行,行与行之间相隔两行。
/* Module A
---------------------------------------------------------------- */
.mod_a {}
/* Module B
---------------------------------------------------------------- */
.mod_b {}
/* Module A ---------------------------------------------------- */
.mod_a {}
/* Module B ---------------------------------------------------- */
.mod_b {}
在样式文件编码声明 @charset
语句下面注明页面名称、作者、创建日期等信息。
@charset "UTF-8";
/**
* @description File Info
* @author Author Name
* @date 2015-10-10
*/
JavaScript
文件注释单行注释使用 //
,注释应单独一行写在被注释对象的上方,不要追加在某条语句的后面。
// is current tab
const active = true
const active = true // is current tab
注释行的上方需要有一个空行(除非注释行上方是一个块的顶部),以增加可读性。
function getType () {
console.log('fetching type...')
// set the default type to 'no type'
const type = this.type || 'no type'
return type
}
// 注释行上面是一个块的顶部时不需要空行
function getType () {
// set the default type to 'no type'
const type = this.type || 'no type'
return type
}
function getType () {
console.log('fetching type...')
// set the default type to 'no type'
const type = this.type || 'no type'
return type
}
多行注释使用 /** ... */
,而不是多行的 //
。
/**
* @name make() returns a new element
* @description based on the passed-in tag name
* @param { Boolean } tag tag name
* @returns { String } element name
*/
function make (tag) {
// ...
return element
}
// make() returns a new element
// based on the passed in tag name
function make (tag) {
// ...
return element
}
注释内容和注释符之间需要有一个空格,以增加可读性。eslint: spaced-comment。
// is current tab
const active = true
/**
* @name make() returns a new element
* @description based on the passed-in tag name
* @param { Boolean } tag tag name
* @returns { String } element name
*/
function make(tag) {
// ...
return element
}
//is current tab
const active = true
/**
*make() returns a new element
*based on the passed-in tag name
*/
function make(tag) {
// ...
return element
}
有时我们发现某个可能的 bug
,但因为一些原因还没法修复;或者某个地方还有一些待完成的功能,这时我们需要使用相应的特殊标记注释来告知未来的自己或合作者。常用的特殊标记有两种:
// FIXME
: 说明问题是什么
// TODO
: 说明还要做什么或者问题的解决方案
class Calculator extends Abacus {
constructor () {
super ()
// FIXME: shouldn’t use a global here
total = 0
// TODO: total should be configurable by an options param
this.total = 0
}
}
文档类注释,如函数、类、文件、事件等;尽量使用 jsdoc
规范。
/**
* Book类,代表一个书本.
* @constructor
* @param {string} title - 书本的标题.
* @param {string} author - 书本的作者.
*/
function Book (title, author) {
this.title = title
this.author = author
}
Book.prototype = {
/**
* 获取书本的标题
* @returns {string|*}
*/
getTitle: function () {
return this.title
},
/**
* 设置书本的页数
* @param pageNum {number} 页数
*/
setPageNum: function (pageNum) {
this.pageNum=pageNum
}
}
var
定义变量,使用let
定义变量,const
定义常量const bar = 1;
var a = 1;
bar = 1;
const sortTable = () => {
console.log(newIndex, oldIndex);
console.log(proTable.value?.tableData);
ElMessage.success("修改成功");
};
>
多行元素放在最后一行的末尾,而不是放在下一行
...#slot
...#slot
const handleClick = param => {
...
}
const getArrList = param => param * 2
const myArray = ref(['item1', 'item2', 'item3'])
const address = reactive<Address>({
province: "",
city: "",
district: "",
address: "",
lnglat: [114.525918, 38.032612],
});
const handleClick = () => {
...
}
const myArray = ref(['item1', 'item2', 'item3'])
const address = reactive<Address>({
...
});
const handleClick = () => {
...
}
// 推荐
const treeRef = ref<InstanceType<typeof ElTree>>();
const treeData = ref<{ [key: string]: any }[]>([]);
const treeAllData = ref<{ [key: string]: any }[]>([]);
// 栅格间隔与样式
const gutter = 10;
const gutterStyle = computed(() => {
return {
width: `calc(100% + ${gutter}px)`,
"margin-bottom": `${gutter}px`
};
});
// 亦可
const amapFlag = ref<boolean>(false);
const handleAmapChange = () => {
amapFlag.value = true;
};
defineExpose({
iMap
});
const unused = 1;
const empty = () => {};
@ts-ignore
// @ts-ignore: Object is possibly 'null'.
const value = possiblyNullValue.someProperty;
GIT
提交规范commit
规范:(类型和描述之间加空格)
feat: 新功能
feat: 新功能
types
: 提交类型
{ value: "feat", name: "特性: 新增功能", emoji: "" },
{ value: "fix", name: "修复: 修复缺陷", emoji: "" },
{ value: "docs", name: "文档: 文档变更", emoji: "" },
{ value: "style", name: "格式: 代码格式(不影响功能,例如空格、分号等格式修正)", emoji: "" },
{ value: "refactor", name: "重构: ♻️ 代码重构(不包括 bug 修复、功能新增)", emoji: "♻️" },
{ value: "perf", name: "性能: ⚡️ 性能优化", emoji: "⚡️" },
{ value: "test", name: "测试: ✅ 添加疏漏测试或已有测试改动", emoji: "✅" },
{ value: "build", name: "构建: ️ 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)", emoji: "️" },
{ value: "ci", name: "集成: 修改 CI 配置、脚本", emoji: "" },
{ value: "revert", name: "回退: ⏪️ 回滚 commit", emoji: "⏪️" },
{ value: "chore", name: "其他: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: "" },
{ value: "wip", name: "开发: 正在开发中", emoji: "" },
{ value: "workflow", name: "工作流: 工作流程改进", emoji: "" },
{ value: "types", name: "类型: 类型定义文件修改", emoji: "" }
规范的目的在于确保一致性、减少错误、提高工作效率,让大家能编写出高质量的代码,更好促进沟通和协作。