import xx from "../xxx";
export default {
name: "xxx", //名称
inject: ["xxx"],//注入
mixins: [xxx], //混入
props: { //接入参数
propsXx: {
type: [Object...],
default: null,
require: true,
validator: t => {
....
}
}
},
data: () => ({ //属性
xx: null
}),
computed: { //计算属性
computedXx() {
...
}
},
watch: { //监听
xxx: {
immediate: false,
handler: (nv, ov) => {
...
}
}
},
methods: { //方法
renderXx(h) {
...
}
},
mounted() { //生命周期勾子
...
},
render(h) { //render入口
...
}
}
- 文件夹名称,多个单词时,使用-连接,如:app-base-config
- Vue可复用组件文件名,前缀:Comp,如:CompAppBaseInfoCard
- Vue基础组件文件名,前缀:BaseComp,如:BaseCompErrorCard
- Vue页面入口文件名,后缀:index,如:AppBaseInfoIndex
- Vue api接口方法名,前缀:ajax,如:ajaxGetAppBaseinfo
- Vue props属性名,前缀:props,如:propsAppId
- Vue computed计算属性名,前缀:computed,如:computedAppId
- Vue emit事件名,前缀:emit,如:emitInput
组件名应该始终是多个单词的,根组件 App 除外。
正例:
export default {
name: 'CompTodoItem',
// ...
}
反例:
export default {
name: 'CompTodo',
// ...
}
单文件组件的文件名应该始终是单词大写开头 (PascalCase)
正例:
components/
|- CompMyComponent.js
反例:
components/
|- myComponent.js
|- mycomponent.js
组件名应该倾向于完整单词而不是缩写。
正例:
components/
|- CompStudentDashboardSettings.js
|- CompUserProfileOptions.js
复制代码
反例:
components/
|- SdSettings.js
|- UProfOpts.js
【强烈建议】应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 Base、App 或 V。
正例:
components/
|- BaseCompButton.js
|- BaseCompTable.js
|- BaseCompIcon.js
反例:
components/
|- MyButton.js
|- VueTable.js
|- Icon.js
【强烈建议】只应该拥有单个活跃实例的组件应该以 The 前缀命名,以示其唯一性。
这不意味着组件只可用于一个单页面,而是每个页面只使用一次。这些组件永远不接受任何 prop,因为它们是为你的应用定制的,而不是它们在你的应用中的上下文。如果你发现有必要添加 prop,那就表明这实际上是一个可复用的组件,只是目前在每个页面里只使用一次。
正例:
components/
|- TheHeading.js
|- TheSidebar.js
反例:
components/
|- Heading.js
|- MySidebar.js
【强烈建议】和父组件紧密耦合的子组件应该以父组件名作为前缀命名。
如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字上。因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。
正例:
components/
|- CompTodoList.js
|- CompTodoListItem.js
|- CompTodoListItemButton.js
components/
|- CompSearchSidebar.js
|- CompSearchSidebarNavigation.js
复制代码
反例:
components/
|- SearchSidebar.js
|- NavigationForSearchSidebar.js
【强制】语义化、功能化。常量全大写,用下划线连接
// 普通变量
let arrayIndex = 0;
// 常量
const HOURS_PER_DAY = 24;
/**
* 同步id获取ddl详情
*
* @param id
* @returns {object}
*/
ajaxGetDdlOptionsById(id) {
return ddl;
}
文件命名参照项目命名规则
正例:DateFormaUtils.js
枚举定义在单独的文件中,例如:ProgrammingLanguageTypeEnum.js
// good
export const ProgrammingLanguageTypeEnum = {
Java: {
label: 'Java',
value: 1,
icon: 'mdi-language-java',
bgColor: 'bg-primary'
},
NodeJS: {
label: 'Node.js',
value: 2,
icon: 'mdi-nodejs',
bgColor: 'bg-secondary'
},
Static: {
label: 'Static',
value: 3,
icon: 'mdi-language-html5',
bgColor: 'bg-positive'
}
}
export const ProgrammingLanguageTypeEnumForNumber = {
1: ProgrammingLanguageTypeEnum.Java,
2: ProgrammingLanguageTypeEnum.NodeJS,
3: ProgrammingLanguageTypeEnum.Static,
}
export const ProgrammingLanguageTypeOptions = Object.keys(ProgrammingLanguageTypeEnumForNumber).map(key => (
{
label: ProgrammingLanguageTypeEnumForNumber[key].label,
value: ProgrammingLanguageTypeEnumForNumber[key].value,
icon: ProgrammingLanguageTypeEnumForNumber[key].icon,
}
))
【强烈建议】在派发/监听事件的时候,事件最终会被自动转换为短横线式命名(kebab-case)。在声明时间的时候,命名可以为短横线式,但为增强可读性强烈建议使用带类型的驼峰格式,例如:
// Emitting
this.$emit('emitEvent') // instead of emitEvent
// Listening
on:emitEvent
【强烈建议】保持计算属性的原子性
正例:
computed: {
basePrice: function () {
return this.manufactureCost / (1 - this.profitMargin)
},
discount: function () {
return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function () {
return this.basePrice - this.discount
}
}
反例:
computed: {
price: function () {
var basePrice = this.manufactureCost / (1 - this.profitMargin)
return (
basePrice -
basePrice * (this.discountPercent || 0)
)
}
}
【强制】Props 定义应该尽量详细,必须需要指定其类型。
【强烈建议】Props原子化:虽然 Vue.js 支持传递复杂的 JavaScript 对象通过 props 属性,但是你应该尽可能的使用原始类型的数据。尽量只使用 JavaScript 原始类型(字符串、数字、布尔值)和函数。尽量避免复杂的对象
正例:
props: {
status: String
}
// 更好的做法!
props: {
propsStatus: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'versionConflict',
'error'
].indexOf(value) !== -1
}
}
}
反例:
// 这样做只有开发原型系统时可以接受
props: ['status']
【强烈建议】总是用 key 配合 .map(v-for)。
在多个重复子组件上必须用 key,以便维护内部组件及其子树的状态。甚至在元素上维护可预测的行为,比如动画中的对象固化 (object constancy),也是一种好的做法。
正例:
filterList.map(db => [
this.renderDbCatalogItem(h, db),
h('q-item-separator', {
staticClass: 'q-ma-none'})
])])
renderDbCatalogItem(h, db) {
return h('div', {
staticClass: 'pp-selectable-bg q-pl-sm q-pr-sm flex no-wrap justify-between cursor-pointer',
key: db.id,
}, [])
}
反例:
renderDbCatalogItem(h, db) {
return h('div', {
staticClass: 'pp-selectable-bg q-pl-sm q-pr-sm flex no-wrap justify-between cursor-pointer',
}, [])
}
【强烈建议】页面跳转数据传递使用路由参数
页面跳转,例如 A 页面跳转到 B 页面,需要将 A 页面的数据传递到 B 页面,推荐使用 路由参数进行传参,而不是将需要传递的数据保存 vuex,然后在 B 页面取出 vuex 的数据,因为如果在 B 页面刷新会导致 vuex 数据丢失,导致 B 页面无法正常显示数据。
let id = ' 123';
this.$router.push({
path: '/user_center', query: {
id: id } });
【强烈建议】使用路由懒加载(延迟加载)机制
{
path: '/uploadAttachment',
name: 'uploadAttachment',
meta: {
title: '上传附件'
},
component: () => import('@/view/components/uploadAttachment/index.vue')
},
【强烈建议】下列关键字后必须有大括号(即使代码块的内容只有一行):
if, else, for, while, do, switch, try, catch, finally
// not good
if (condition)
doSomething();
// good
if (condition) {
doSomething();
}
【强烈建议】不要直接使用 undefined 进行变量判断;使用 typeof 和字符串’undefined’对变量进行判断。
// not good (person未定义时,以下语句会报错)
if (person === undefined) {
...
}
// good
if (typeof person === 'undefined') {
...
}
【建议】语句以分号结束
这个是要引起注意的,比如:
// bad
a = b // 赋值
(function(){
//....
})() // 自执行函数
// good
a = b; // 赋值
(function(){
//....
})() // 自执行函数
未加分号,结果被解析成
a = b(function(){
/*...*/})() //将b()()返回的结果赋值给a
【强制】值比较使用===, ==执行比较前会做类型转换
【强制】
缩进:使用IDE默认格式化代码方法进行格式化
switch:逻辑分支必须包含default
…
【强烈建议】核心、复杂逻辑添加必要注释(单行)
// 获取用户上次选的oaBu
if (localStorage.getItem('oa_bu')) {
this.model.oaBu = JSON.parse(localStorage.getItem('oa_bu'))
}
【强烈建议】方法注释参考JAVA规范, 以/**开头(多行)
/**
* 获取两个时间戳的可读差值
*
* @param startTime
* @param endTime
* @returns {string}
*/
export const getTimeDiff = (startTime, endTime) => {
let dateBegin = new Date(startTime.replace(/-/g, "/"))
let dateEnd = endTime === null ? new Date() : new Date(endTime.replace(/-/g, "/"))
let time = dateEnd.getTime() - dateBegin.getTime()
let duration = (time / (60 * 60 * 1000)).toFixed(2)
let display = duration < 24 ? `${
duration} 小时` : `${
(duration / 24).toFixed(2)} 天`
return display
}
【强烈建议】始终基于模块的方式来构建你的工程,每一个子模块只做一件事情。
Vue.js 的设计初衷就是帮助开发者更好的开发界面模块。一个模块是应用程序中独立的一个部分。
每一个 Vue 组件(等同于模块)首先必须专注于解决一个单一的问题,独立的、可复用的、微小的 和 可测试的。
如果你的组件做了太多的事或是变得臃肿,请将其拆分成更小的组件并保持单一的原则。一般来说,尽量保证每一个文件的代码行数不要超过 500 行。也请保证组件可独立的运行。比较好的做法是增加一个单独的 demo 示例。
使用场景:组件的行为和属性类似,例如:模态框
【强制】基础文件命名,例如:MixinBaseModal.js
【强制】mixin组件必须实现的方法前缀必须是abstract,例如:abstractRenderContents()
【强制】为了将Mixin的属性与组件的属性相区分,我们使用
$_
,原因如下:
- 这是Vuejs传统风格
_
在Vuejs中表示私有属性$
属于Vue的保留字
在风格指南可以看到官方推荐的Mixin命名:
data: () => ({
$_myMixin_updateUser: false,
}),
methods: {
$_hide() {
this.loading = false;
this.hide()
},
}
使用注意事项:
避免写新的MixinBase
尽量避免同时mixin多个对象
引入单独的功能性方法,尽量使用import而不是mixin
Mixin注意事项:
合并:当混合对象与组件包含同名选项时,这些选项将以适当的策略合并。例如,同名钩子函数被并入一个数组,因而都会被调用。另外,混合的钩子将在组件自己的钩子之前调用。
冲突:值为对象的选项,如 methods, components 和 directives 将合并到同一个对象内。如果键冲突则组件的选项优先。
【强烈建议】服务端发生错误时,返回给前端的响应信息必须包含 HTTP 状态码,errorCode、 errorMessage、用户提示信息四个部分。
【强烈建议】在前后端交互的 JSON 格式数据中,所有的 key 必须为小写字母开始的 lowerCamelCase 风格,符合英文表达习惯,且表意完整。
正例:errorCode / errorMessage / assetStatus / menuList / orderList / configFlag
反例:ERRORCODE / ERROR_CODE / error_message / error-message / errormessage / ErrorMessage / msg
【强烈建议】对于需要使用超大整数的场景,服务端一律使用 String 字符串类型返回,禁止使用 Long 类型。
说明:Java 服务端如果直接返回 Long 整型数据给前端,JS 会自动转换为 Number 类型(注:此类型为双 精度浮点数,表示原理与取值范围等同于 Java 中的 Double)。Long 类型能表示的最大值是 2 的 63 次方 -1,在取值范围之内,超过 2 的 53 次方 (9007199254740992)的数值转化为 JS 的 Number 时,有些数 值会有精度损失。扩展说明,在 Long 取值范围内,任何 2 的指数次整数都是绝对不会存在精度损失的,所 以说精度损失是一个概率问题。若浮点数尾数位与指数位空间不限,则可以精确表示任何整数,但很不幸, 双精度浮点数的尾数位只有 52 位。 反例:通常在订单号或交易号大于等于 16 位,大概率会出现前后端单据不一致的情况,比如,“orderId”: 362909601374617692,前端拿到的值却是: 362909601374617660。
【强制】HTTP 请求通过 URL 传递参数时,不能超过 2048 字节。
说明:不同浏览器对于 URL 的最大长度限制略有不同,并且对超出最大长度的处理逻辑也有差异,2048 字节是取所有浏览器的最小值。 Java 开发手册 27/59 反例:某业务将退货的商品 id 列表放在 URL 中作为参数传递,当一次退货商品数量过多时,URL 参数超长, 传递到后端的参数被截断,导致部分商品未能正确退货。
【强制】HTTP 请求通过 body 传递内容时,必须控制长度,超出最大长度后,后端解析会出错。
说明:nginx 默认限制是 1MB,tomcat 默认限制为 2MB,当确实有业务需要传较大内容时,可以通过调 大服务器端的限制。
ESLint - 支持jsx
Vue官方风格指南
前端规范指南(鹅厂)
Vue.js 最佳实践
Java开发手册(阿里嵩山版)
前端规范