文章目录
- 前言
- 命名规范
- 项目命名
- 目录命名
- 文件命名
- 命名严谨性
- HTML 书写规范
- 结构、样式、行为分离
- 缩进
- 文件编码
- 语义化
- IE 兼容模式
- viewport
- 为移动端设备优化,设置可见区域的宽度和初始缩放比例
- iOS 图标
- favicon(网站图标,移动端默认可用于添加到桌面)
- 一律使用小写元素名
- 关闭所有 HTML 元素
- Class 与 ID
- 关闭空的 HTML 元素
- 使用小写属性名
- 属性值
- 图片属性
- 空格和等号
- 空行和缩进
- 样式表
- 在 HTML 中的 script 标签
- 省略外链资源 URL 协议部分
- CSS 书写规范
- 代码组织
- Class 和 ID
- 类选择器口诀
- 声明顺序
- 引号使用
- 媒体查询(Media query)的位置
- 不要使用 @import
- 链接的样式顺序:
- 使用 vw 作为单位时的简便计算
- JavaScript 书写规范
- 命名
- 块级作用域
- 强类型检查
- 变量
- 函数
- 条件语句
- 字符串
- 解构赋值
- 数组
- 对象
- Vue 开发相关规范
- 组件规范
- 1、组件名为多个单词
- 2、组件文件名为 pascal-case 格式
- 3、基础组件文件名为 base 开头,使用完整单词而不是缩写
- 4、和父组件紧密耦合的子组件应该以父组件名作为前缀命名
- 5、在 Template 模版中使用组件,应使用 PascalCase 模式,并且使用自闭合组件
- 6、组件的 data 必须是一个函数
- 7、Prop 定义应该尽量详细
- 8、为组件样式设置作用域(使用 `scoped` 属性)
- 9、如果特性元素较多,应该主动换行
- 指令都使用缩写形式
- 标签顺序保持一致
- 必须为 v-for 设置键值 key
- v-show 与 v-if 选择
- Vue Router 规范
- 1、页面跳转数据传递使用路由参数
- 2、使用路由懒加载(延迟加载)机制
- 3、router 中的命名规范
- 4、router 中的 path 命名规范
- 5、router 规范
- service 目录规范
- 其他
- 1、尽量不要手动操作 DOM
- 2、删除无用代码(因使用了 Git/SVN 版本管理,应及时一些调试代码及无用弃用的代码)
前言
现代软件架构的复杂性需要协同开发完成,如何高效地协同呢?无规矩不成方圆,无规范难以协同,比如,制订交通法规表面上是要限制行车权,实际上是保障公众的人身安全。对软件来说,适当的规范和标准绝不是消灭代码内容的创造性、优雅性,而是限制过度个性化,以一种普遍认可的统一方式一起做事,提升协作效率,降低沟通成本。代码的字里行间流淌的是软件系统的血液,质量的提升是尽可能少踩坑,杜绝踩重复的坑,切实提升系统稳定性,码出质量。
命名规范
项目命名
全部采用小写方式, 以中划线分隔。
正例:mall-management-system
反例:mall_management-system | mallManagementSystem
目录命名
全部采用小写方式, 以中划线分隔,有复数结构时,要采用复数命名法, 缩写不用复数
正例: scripts | styles | components | images | utils | layouts | demo-styles | demo-scripts | img | doc
反例: script | style | demo_scripts | demoStyles | imgs | docs
【特殊】VUE 的项目中的 components 中的组件目录,使用 kebab-case 命名
正例: head-search | page-loading | authorized | notice-icon
反例: HeadSearch | PageLoading
【特殊】VUE 的项目中的除 components 组件目录外的所有目录也使用 kebab-case 命名
正例: page-one | shopping-car | user-management
反例: ShoppingCar | UserManagement
文件命名
全部采用小写方式, 以中划线分隔
正例: render-dom.js / signup.css / index.html / company-logo.png
反例: renderDom.js / UserManagement.html
命名严谨性
代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。
!> 注意,即使纯拼音命名方式也要避免采用
正例:henan | luoyang | rmb 等国际通用的名称,可视同英文。
反例:DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3
!> 杜绝完全不规范的缩写,避免望文不知义:反例:AbstractClass“缩写”命名成 AbsClass;condition“缩写”命名成 condi,此类随意缩写严重降低了代码的可阅读性。
HTML 书写规范
结构、样式、行为分离
尽量确保文档和模板只包含 HTML 结构,样式都放到样式表里,行为都放到脚本里。
缩进
统一两个空格缩进(总之缩进统一即可),不要使用 Tab 或者 Tab、空格混搭。
文件编码
- 使用不带 BOM 的 UTF-8 编码。
- 在 HTML 中指定编码
<meta charset="utf-8">
; - 无需使用 @charset 指定样式表的编码,它默认为 UTF-8;
语义化
没有 CSS 的 HTML 是一个语义系统而不是 UI 系统。
通常情况下,每个标签都是有语义的,此外语义化的 HTML 结构,有助于机器(搜索引擎)理解,另一方面多人协作时,能迅速了解开发者意图。
IE 兼容模式
优先使用最新版本的 IE 和 Chrome 内核
<meta http-equid="X-UI-Compatible" content="IE=edge,chrome=1" />
viewport
一般指的是浏览器窗口内容区的大小,不包含工具条、选项卡等内容;
viewport 是用户网页的可视区域。
手机浏览器是把页面放在一个虚拟的"窗口"(viewport)中,通常这个虚拟的"窗口"(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的网页的布局),用户可以通过平移和缩放来看网页的不同部分。
width
: 浏览器宽度,输出设备中的页面可见区域宽度;device-width
: 设备分辨率宽度,输出设备的屏幕可见宽度;initial-scale
: 初始缩放比例;minimum-scale
:允许用户缩放到的最小比例。maximum-scale
: 最大缩放比例;user-scalable
:用户是否可以手动缩放。
为移动端设备优化,设置可见区域的宽度和初始缩放比例
<metaname="viewport"content="width=device-width, initial-scale=1 user-scalable=no"
/>
iOS 图标
apple-touch-icon
图片自动处理成圆角和高光等效果;apple-touch-icon-precomposed
禁止系统自动添加效果,直接显示设计原图;
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<linkrel="apple-touch-icon-precomposed"sizes="152x152"href="gitbook/images/apple-touch-icon-precomposed-152.png"
/>
favicon(网站图标,移动端默认可用于添加到桌面)
在未指定 favicon 时,大多数浏览器会请求 Web Server 根目录下的 favicon.ico 。为了保证 favicon 可访问,避免 404,必须遵循以下两种种方法之一:
- 在 Web Server 根目录放置 favicon.ico 文件;
- 使用 link 指定 favicon(SPA 推荐直接使用 base64, 多页模式直接使用相对路径的 ico 文件);
<linkrel="shortcut icon"href="gitbook/images/favicon.ico"type="image/x-icon"
/>
一律使用小写元素名
推荐使用小写字母:
- 混合了大小写的风格是非常糟糕的。
- 开发人员通常使用小写 (类似 XHTML)。
- 小写风格看起来更加清爽。
- 小写字母容易编写。
<!-- 推荐 -->
<section><p>这是一个段落。</p>
</section>
/* 推荐 */
color: #d5d5d5;
/* 不好 */
/* COLOR: #d5d5d5; */
关闭所有 HTML 元素
在 HTML5 中, 你不一定要关闭所有元素 (例如 <p>
元素),但我们建议每个元素都要添加关闭标签。
- 自闭合(self-closing)标签,无需闭合 ( 例如: img input br hr 等 );
- 可选的闭合标签(closing tag),需闭合 ( 例如:
- 或 );
- 尽量减少标签数量;
Class 与 ID
- class 应以功能或内容命名,不以表现形式命名;
- class 与 id 单词字母小写,多个单词组成时,采用中划线-分隔;
- 使用唯一的 id 作为 Javascript hook, 同时避免创建无样式信息的 class;
关闭空的 HTML 元素
在 HTML5 中, 空的 HTML 元素必须关闭:
<!-- 我们可以这么写: -->
<meta charset="utf-8" />
目前在HTML中有以下这些空元素: <area>
<base>
<br>
<col>
<colgroup>
<command>
<embed>
<hr>
<img>
<input>
<keygen>
<link>
<meta>
<param>
<source>
<track>
<wbr>
使用小写属性名
HTML5 属性名允许使用大写和小写字母,但我们要求使用小写字母属性名:
- 同时使用大小写是非常不好的习惯。
- 开发人员通常使用小写 (类似 XHTML)。
- 小写风格看起来更加清爽。
- 小写字母容易编写。
属性值
HTML5 属性值可以不用引号,但是我们要求必须使用引号:
- 如果属性值含有空格需要使用引号。
- 混合风格不推荐的,建议统一风格。
- 属性值使用引号易于阅读。
图片属性
图片通常使用 alt
属性。 在图片不能显示时,它能替代图片显示。
定义好图片的尺寸,在加载时可以预留指定空间,减少闪烁。
空格和等号
等号前后必须使用空格
<!-- 推荐 -->
<link rel="stylesheet" href="styles.css" />
<!-- 不推荐 -->
<link rel\ =\ "stylesheet" href\ =\ "styles.css" />
空行和缩进
- 为每个逻辑功能块添加空行,这样更易于阅读。
- 缩进使用两个空格,不建议使用 TAB。
- 比较短的代码间不要使用不必要的空行和缩进。
样式表
样式表使用简洁的语法格式 ( type 属性不是必须的)
<link rel="stylesheet" href="styles.css" />
内嵌样式规则:
- 将左花括号与选择器放在同一行。
- 左花括号与选择器间添加一个空格。
- 使用两个空格来缩进。
- 冒号与属性值之间添加一个空格。
- 逗号和符号之后使用一个空格。
- 每个属性与值结尾都要使用分号。
- 只有属性值包含空格时才使用引号。
- 右花括号放在新的一行。
p.into {font-family: Verdana;font-size: 16em;
}
在 HTML 中的 script 标签
- 标签的 type 属性不是必须的
- 请加上 defer 属性
省略外链资源 URL 协议部分
省略外链资源(图片及其它媒体资源)URL 中的 http / https 协议,使 URL 成为相对地址,避免 Mixed Content 问题,减小文件字节数。
其它协议(ftp 等)的 URL 不省略。
CSS 书写规范
代码组织
- 以组件为单位组织代码段;
- 制定一致的注释规范;
- 组件块和子组件块以及声明块之间使用一空行分隔,子组件块之间三空行分隔;
- 如果使用了多个 CSS 文件,将其按照组件而非页面的形式分拆,因为页面会被重组,而组件只会被移动;
良好的注释是非常重要的。请留出时间来描述组件(component)的工作方式、局限性和构建它们的方法。不要让你的团队其它成员 来猜测一段不通用或不明显的代码的目的。
Class 和 ID
- 使用语义化、通用的命名方式;
- 使用连字符 - 作为 ID、Class 名称界定符,不要驼峰命名法和下划线;
- 避免选择器嵌套层级过多,尽量少于 3 级;
- 避免选择器和 Class、ID 叠加使用;
出于性能考量,在没有必要的情况下避免元素选择器叠加 Class、ID 使用。
元素选择器和 ID、Class 混合使用也违反关注分离原则。如果 HTML 标签修改了,就要再去修改 CSS 代码,不利于后期维护。
类选择器口诀
样式点定义,结构类(class)调用,一个或多个,开发最常用
- 类选择器使用"."进行标识,后面紧跟类名(自定义);
- 可以理解为给这个标签起一个名字;
- 长名称或者词组可以使用中横线来为选择器命名;
- 不要使用纯数字、中文等命名,尽量使用英文字母来表示;
- 命名要有意义,尽量使别人一眼就知道这个类名的目的;
声明顺序
相关属性应为一组,推荐的样式编写顺序,保证更好的可读性和可扫描重要
- Positioning
- Box model
- Typographic
- Visual
由于定位(positioning)可以从正常的文档流中移除元素,并且还能覆盖盒模型(box model)相关的样式,因此排在首位。盒模型决定了组件的尺寸和位置,因此排在第二位。
其他属性只是影响组件的内部(inside)或者是不影响前两组属性,因此排在后面。
作为最佳实践,我们应该遵循以下顺序(应该按照下表的顺序):
结构性属性:
- display
- position, left, top, right
- overflow, float, clear
- margin, padding
表现性属性:
- background, border
- font, text
引号使用
url() 、属性选择符、属性值使用双引号。
媒体查询(Media query)的位置
将媒体查询放在尽可能相关规则的附近。不要将他们打包放在一个单一样式文件中或者放在文档底部。如果你把他们分开了,将来只会被大家遗忘。
不要使用 @import
与 <link> 相比,@import 要慢很多,不光增加额外的请求数,还会导致不可预料的问题。
替代办法:
- 使用多个 元素;
- 通过 Sass 或 Less 类似的 CSS 预处理器将多个 CSS 文件编译为一个文件;
- 其他 CSS 文件合并工具;
链接的样式顺序:
a:link -> a:visited -> a:hover -> a:active(LoVeHAte)
选择字体
在 Web 上应用字体,是一门技术,同时也是一门艺术. 由于计算机历史发展的原因,西文有大量优秀的字体可供选择,可对于中文来说就是一项挑战. 主流操作系统提供的本地中文字体极少,另一方面中文字体组成的特殊性,其体积过于庞大,无法良好地使用 webfont. 所以编写健壮的 font-family 是一件需要深思熟虑的事情.
使用 vw 作为单位时的简便计算
以 iphone6 为标准的 750*1334px 的设计稿为例,在 scss 中使用如下方法,可以直接使用设计稿上面的标志,快速编写 css,免于转换计算
@function vw($px) {@return ($px / 750) * 100vw;
}div {width: vw(101);
}
JavaScript 书写规范
命名
-
采用小写驼峰命名 lowerCamelCase,代码中的命名均不能以下划线,也不能以下划线或美元符号结束。
Bad:
_name | name_ | name$
; -
方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从驼峰形式。
Good:
localValue | getHttpMessage() | inputUserId
-
常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
例子:
Good: MAX_STOCK_COUNT; Bad: MAX_COUNT
!> 其中 method 方法命名强调 动词 或者 动词+名词 形式
附: 函数方法常用的动词(点击展开):// 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 聚集
块级作用域
let
取代 var
,在 let
和 const
之间,建议优先使用 const
,尤其是在全局环境,不应该设置变量,只应设置常量。
强类型检查
=== 代替 ==
0 == false; // true
0 === false; // false
2 == '2'; // true
2 === '2'; // false// 例子
const value = '500';
if (value === 500) {console.log(value);
}if (value === '500') {console.log(value);
}
变量
1、给变量命名时,应该要使变量名具有代表意图的象征,使人易于搜索并且容易理解。
Bad:
let daysSLV = 10;
let y = new Date().getFullYear();let ok;
if (user.age > 30) {ok = true;
}
Good:
const MAX_AGE = 30;
let daysSinceLastVisit = 10;
let currentYear = new Date().getFullYear();
...
const isUserOlderThanAllowed = user.age > MAX_AGE;
2、不要在变量名中增加没必要额外的单词
Bad:
let nameValue;
let theProduct;
Good:
let name;
let product;
3、不要强制记忆变量名的上下文
Bad:
const users = ['John', 'Marco', 'Peter'];
users.forEach((u) => {doSomething();doSomethingElse();// ...register(u);
});
Good:
const users = ['John', 'Marco', 'Peter'];
users.forEach((user) => {doSomething();doSomethingElse();// ...register(user);
});
4、变量名不要加上下文重复的单词
Bad:
const user = {userName: "John",userSurname: "Doe",userAge: "28"
};
...
user.userName;
Good:
const user = {name: "John",surname: "Doe",age: "28"
};
...
user.name;
函数
1、函数名应该是动词或者短语,代表某种行为,描述它们在做什么
Bad:
function notif(user) {// ...
}
Good:
function notifyUser(emailAddress) {// ...
}
2、避免使用大量的参数,理想的情况就是用两个或者更少的参数。参数越少,测试就越容易
Bad:
function getUsers(fields, fromDate, toDate) {// implementation
}
Good:
function getUsers({ fields, fromDate, toDate }) {// implementation
}getUsers({fields: ['name', 'surname', 'email'],fromDate: '2019-01-01',toDate: '2019-01-18'
});
3、一个函数应该做一件事,避免在一个函数中执行多个操作。
Bad:
function notifyUsers(users) {users.forEach((user) => {const userRecord = database.lookup(user);if (userRecord.isVerified()) {notify(user);}});
}
Good:
function notifyVerifiedUsers(users) {users.filter(isUserVerified).forEach(notify);
}function isUserVerified(user) {const userRecord = database.lookup(user);return userRecord.isVerified();
}
4、使用 Object.assign
设置默认对象。
Bad:
const shapeConfig = {type: 'cube',width: 200,height: null
};
function createShape(config) {config.type = config.type || 'cube';config.width = config.width || 250;
}
createShape(shapeConfig);
Good:
const shapeConfig = {type: 'cube',width: 200// ...
};function createShape(config) {config = Object.assign({type: 'cube',width: 250// ...},config);// ...
}createShape(shapeConfig);
5、不要使用标志记作为参数,因为它们告诉你该函数正在做的比它应该做的更多。
Bad:
function createFile(name, isPublic) {if (isPublic) {fs.create(`./public/${name}`);} else {fs.create(name);}
}
Good:
function createFile(name) {fs.create(name);
}function createPublicFile(name) {createFile(`./public/${name}`);
}
6、不要污染全局变量。如果需要扩展现有对象,请使用 ES6 类和继承,而不是在现有对象的原型链上创建函数
Bad:
Array.prototype.myFunc = function myFunc() {// ...
};
Good:
class SuperArray extends Array {myFunc() {// ...}
}
7、重要函数或者类等都要添加头描述
条件语句
1、使用条件语句尽量短点。这可能是微不足道的,但值得一提。此方法仅用于布尔值,并且如果您确定该值不是未定义的或为 null
。
Bad:
if (isValid === true) {// ...
}if (isValid === false) {// ...
}
Good:
if (isValid) {// ...
}if (!isValid) {// ...
}
2、尽可能避免 switch 分支,请改用多态和继承。
字符串
1、应使用数组保存字符串片段,使用时调用 join
方法。避免使用+或+=的方式拼接较长的字符串,每个字符串都会使用一个小的内存片段,过多的内存片段会影响性能
2、静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。
解构赋值
1、使用数组成员对变量赋值时,优先使用解构赋值。
Bad:
const arr = [1, 2, 3, 4];const first = arr[0];
const second = arr[1];
Good:
const [first, second] = arr;
2、函数的参数如果明确是对象的成员,优先使用解构赋值。
3、如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。这样便于以后添加返回值,以及更改返回值的顺序。
4、不要在函数体内使用 arguments
变量,使用扩展运算符(...)
代替。
数组
1、使用扩展运算符(...)
拷贝数组。使用Array.from
方法,将类似数组的对象转为数组。
const a1 = [1, 2, 3];
const b1 = [...a1];const h3List = Array.from(document.querySelectorAll('h3'));
2、如果单纯判断每个数组元素存在。使用Array.includes
方法。
const a1 = [1, 2, 3];
const b1 = [...a1];const h3List = Array.from(document.querySelectorAll('h3'));
对象
1、尽量不要使用 new
命令,改用 Object.create()
或者对象字面量
// 对象字面量
const lang = { name: 'Javascript' };const lang = Object.create({ name: 'JavaScript' });
Vue 开发相关规范
vue 项目规范以 Vue 官方规范 (https://cn.vuejs.org/v2/style-guide/) 中的 A 规范为基础,在其上面进行项目开发,故所有代码均遵守该规范。
!> 请仔细阅读 Vue 官方规范,切记,此为第一步。
组件规范
1、组件名为多个单词
Good:
export default {name: 'TodoItem'// ...
};
Bad:
export default {name: 'Todo',// ...
}
export default {name: 'todo-item',// ...
}
2、组件文件名为 pascal-case 格式
Good:
components/|- my-component.vue
Bad:
components/|- myComponent.vue|- MyComponent.vue
3、基础组件文件名为 base 开头,使用完整单词而不是缩写
Good:
components/|- base-button.vue
Bad:
components/|- MyButton.vue
4、和父组件紧密耦合的子组件应该以父组件名作为前缀命名
Good:
components/|- todo-list.vue|- todo-list-item.vue|- todo-list-item-button.vue|- user-profile-options.vue (完整单词)
Bad:
components/|- TodoList.vue|- TodoItem.vue|- TodoButton.vue|- UProfOpts.vue (使用了缩写)
5、在 Template 模版中使用组件,应使用 PascalCase 模式,并且使用自闭合组件
Good:
<!-- 在单文件组件、字符串模板和 JSX 中 -->
<MyComponent />
<Row><table :column="data"/></Row>
Bad:
<my-component /> <row><table :column="data"/></row>
6、组件的 data 必须是一个函数
当在组件中使用 data 属性的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。 因为如果直接是一个对象的话,子组件之间的属性值会互相影响。
7、Prop 定义应该尽量详细
- 必须使用 camelCase 驼峰命名
- 必须指定类型
- 必须加上注释,表明其含义
- 必须加上 required 或者 default,两者二选其一
- 如果有业务需要,必须加上 validator 验证
Good:
props: {// 组件状态,用于控制组件的颜色status: {type: String,required: true,validator: function (value) {return ['succ','info','error'].indexOf(value) !== -1}},// 用户级别,用于显示皇冠个数userLevel:{type: String,required: true}
}
8、为组件样式设置作用域(使用 scoped
属性)
9、如果特性元素较多,应该主动换行
Good:
<MyComponentfoo='a'bar='b'baz='c'foo='a'bar='b'baz='c'foo='a'bar='b'baz='c'
/>
指令都使用缩写形式
指令推荐都使用缩写形式,(用 : 表示 v-bind: 、用 @ 表示 v-on: 和用 # 表示 v-slot:)
Good:
<input@input="onInput"@focus="onFocus"
>
Bad:
<inputv-on:input="onInput"@focus="onFocus"
>
标签顺序保持一致
// 保持以下顺序
<template>...</template>
<script>...</script>
<style>...</style>
必须为 v-for 设置键值 key
v-show 与 v-if 选择
如果运行时,需要非常频繁地切换,使用 v-show ;如果在运行时,条件很少改变,使用 v-if。
Vue Router 规范
1、页面跳转数据传递使用路由参数
页面跳转,例如 A 页面跳转到 B 页面,需要将 A 页面的数据传递到 B 页面,推荐使用 路由参数进行传参,而不是将需要传递的数据保存 vuex,然后在 B 页面取出 vuex 的数据,因为如果在 B 页面刷新会导致 vuex 数据丢失,导致 B 页面无法正常显示数据。
let id = '123';
this.$router.push({ name: 'userCenter', query: { id } });
2、使用路由懒加载(延迟加载)机制
3、router 中的命名规范
path
、childrenPoints
命名规范采用 kebab-case 命名规范(尽量 vue 文件的目录结构保持一致,因为目录、文件名都是 kebab-case,这样很方便找到对应的文件)
name
命名规范采用 KebabCase 命名规范且和 component 组件名保持一致!(因为要保持keep-alive
特性,keep-alive
按照 component 的name
进行缓存,所以两者必须高度保持一致)
{path: '/n/task-calling',component: _import('tasks/calling/index'),name: 'taskCalling',desc: '外呼下单',},
4、router 中的 path 命名规范
path 除了采用 kebab-case 命名规范以外,必须以 / 开头,即使是 children 里的 path 也要以 / 开头
目的:经常有这样的场景:某个页面有问题,要立刻找到这个 vue 文件,如果不用以/开头,path 为 parent 和 children 组成的,可能经常需要在 router 文件里搜索多次才能找到,而如果以/开头,则能立刻搜索到对应的组件
5、router 规范
router 目录应根据项目进行业务分层,进行模块拆分,并尽量与 views 模块保持一致。
// router/index.js
import Router from 'vue-router';
import tasks from './modules/tasks';
import sys from './modules/sys';
import business from './modules/business';
import workbench from './modules/workbench';// 路由定义使用说明:
// 代码中路由统一使用name属性跳转
const router = new Router({mode: 'hash',routes: [{path: '/404',component: _import('error/404'),name: '404',desc: '404未找到',},{path: '/login',component: _import('login/index'),name: 'login',desc: '登录',},{path: '/',component: _import('home/index'),name: 'home',},/*---- 系统管理 ------------------------------------------------------------- */...sys,/*---- 业务管理 ------------------------------------------------------------- */...business,/*---- 个人工作台 ------------------------------------------------------------- */...workbench,/*---- 任务执行 ------------------------------------------------------------- */...tasks,]
};
service 目录规范
service 目录存放与后端接口相关的模块,包括接口路径定义,请求相关设置。接口定义必须按照后端结构进行定义。
// 实例
export const common = {captcha: 'captcha.jpg',login: 'sys/login',logout: 'sys/logout'
};export const sys = {user: {list: 'sys/user/list',info: 'sys/user/info',updatePassword: 'sys/user/password',add: 'sys/user/save',update: 'sys/user/update',del: 'sys/user/delete',getUserInfo: 'sys/user/getUserInfo'},menu: {nav: 'sys/menu/nav',select: 'sys/menu/select',list: 'sys/menu/list',info: 'sys/menu/info',add: 'sys/menu/save',update: 'sys/menu/update',del: 'sys/menu/delete'}
};