一、代码规范
1.1 IDE插件
使用 Visual Studio Code 编译器,下载 ESLint 、Prettier - Code formatter、Stylelint 插件
点击编译器左上角文件> 首选项> 设置>右上角编辑json文件, 去掉编译器配置中的关于格式化和规范相关的配置,使编译器读取项目中的配置文件
{
"breadcrumbs.enabled": true,
"editor.renderControlCharacters": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
},
"editor.suggestSelection": "first",
"explorer.confirmDelete": false,
"vsicons.dontShowNewVersionMessage": true,
"workbench.colorTheme": "Monokai",
"explorer.compactFolders": false,
// #去掉代码结尾的分号
"prettier.semi": false,
// #使用带引号替代双引号
"prettier.singleQuote": true,
// #让函数(名)和后面的括号之间加个空格
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
}
1.2 ESLint
// 安装依赖
npm install eslint babel-eslint eslint-config-standard eslint-loader eslint-plugin-html eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard eslint-plugin-vue--save-dev
在项目下新建.eslintrc.js 文件
.eslintrc.js配置
module.exports = {
env: {
browser: true,
node: true,
es6: true,
jest: true,
commonjs: true,
},
extends: ['eslint:recommended', 'plugin:prettier/recommended', 'plugin:vue/essential'],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true,
},
parser: 'babel-eslint',
},
plugins: ['vue', 'prettier'],
rules: {
'prettier/prettier': 2,
/**
* 禁止使用debugger
**/
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
/**
* 禁止使用console
**/
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
/**
* 禁止使用 alert
*/
'no-alert': process.env.NODE_ENV === 'production' ? 'error' : 'off',
/**
* 禁止使用tab
**/
'no-tabs': 'off',
/**
* 首行缩进
*/
indent: 'off',
/**
* 禁止或强制在代码块中开括号前和闭括号后有空格
*/
'block-spacing': 'error',
/**
* 禁止出现未使用过的变量
*/
'no-unused-vars': 'error',
/**
* 在“function”定义的左括号前强制使用一致的间距
*/
'space-before-function-paren': 'off',
/**
* 禁止空格和 tab 的混合缩进
*/
'no-mixed-spaces-and-tabs': 'error',
/**
* 禁止条件表达式中出现赋值操作符
*/
'no-cond-assign': 'error',
/**
* 禁止对象字面量中出现重复的 key
*/
'no-dupe-keys': 'error',
/**
* 数组的方法除了 forEach 之外,回调函数必须有返回值
*/
'array-callback-return': 'error',
/**
* 箭头函数体必须由大括号包裹
* @reason 代码格式问题,最好由 Prettier 解决
*/
'arrow-body-style': 'error',
/**
* 在箭头函数中的箭头前后强制保持一致的间距
*/
'arrow-spacing': [2, { before: true, after: true }],
/**
* 将 var 定义的变量视为块作用域,禁止在块外使用
* @reason 已经禁止使用 var 了
*/
'block-scoped-var': 'error',
/**
* 变量名必须是 camelCase 风格的
* @reason 很多 api 或文件名都不是 camelCase 风格的
*/
camelcase: 'error',
/**
* switch 语句必须有 default
*/
'default-case': 'error',
/**
* switch 语句中的 default 必须在最后
*/
'default-case-last': 'error',
/**
* 必须使用 === 或 !==,禁止使用 == 或 !=
*/
eqeqeq: 'off',
/**
* 属性使用双引号
*/
'jsx-quotes': ['error', 'prefer-double'],
/**
* 单行注释必须写在上一行
*/
'line-comment-position': 'error',
'max-depth': ['error', 5],
/**
* 限制一个文件最多的行数
*/
'max-lines': 'off',
/**
* new 后面的类名必须首字母大写
*/
'new-cap': [
'error',
{
newIsCap: true,
capIsNew: false,
properties: true,
},
],
/**
* 禁止对使用 const 定义的常量重新赋值
*/
'no-const-assign': 'error',
/**
* 禁止解构赋值时出现同样名字的的重命名,比如 let { foo: foo } = bar;
*/
'no-useless-rename': 'error',
/**
* 禁止没必要的 return
*/
'no-useless-return': 'error',
/**
* 禁止使用 var
*/
'no-var': 'error',
/**
* 禁止变量申明时用逗号一次申明多个
*/
'one-var': ['error', 'never'],
/**
* 使用分号
*/
semi: ['error', 'never'],
'vue/camelcase': 'error',
/**
* 修复 no-unused-vars 不检查 jsx 的问题
*/
'vue/jsx-uses-vars': 'error',
/**
* 组件名称必须和文件名一致
*/
'vue/match-component-file-name': 'off',
/**
* 禁止出现重复的属性
*/
'vue/no-duplicate-attributes': [
'error',
{
allowCoexistClass: false,
allowCoexistStyle: false,
},
],
/**
* 禁止修改组件的 props
*/
'vue/no-mutating-props': 'error',
/**
* 禁止出现语法错误
*/
'vue/no-parsing-error': 'error',
/**
* 组件的 name 属性静止使用保留字
*/
'vue/no-reserved-component-names': 'error',
/**
* 禁止覆盖保留字
*/
'vue/no-reserved-keys': 'error',
/**
* 禁止在计算属性中对属性修改
*/
'vue/no-side-effects-in-computed-properties': 'error',
/**
* 禁止 <template> 使用 key 属性
*/
'vue/no-template-key': 'error',
/**
* 模版中的变量名禁止与前一个作用域重名
*/
'vue/no-template-shadow': 'error',
/**
* 禁止使用未注册的组件
*/
'vue/no-unregistered-components': 'off',
/**
* 当你的 vue 版本较老时,禁用还未支持的语法
*/
'vue/no-unsupported-features': 'error',
/**
* 禁止定义在 components 中的组件未使用
*/
'vue/no-unused-components': 'error',
/**
* v-for 指令的元素必须有 v-bind:key
*/
'vue/require-v-for-key': 'error',
/**
* 禁止属性定义了却未使用
*/
'vue/no-unused-properties': 'error',
/**
* 模版中已定义的变量必须使用
*/
'vue/no-unused-vars': 'error',
/**
* 禁止在同一个元素上使用 v-if 和 v-for 指令
*/
'vue/no-use-v-if-with-v-for': 'error',
/**
* props 必须用驼峰式
*/
'vue/prop-name-casing': 'error',
/**
* 计算属性必须有返回值
*/
'vue/return-in-computed-property': 'error',
/**
* vue 组件名称必须是多次,例如GoodDetail,不能是detail
*/
'vue/multi-word-component-names': 0,
},
}
webpack 配置:
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('examples'),resolve('src')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
}
1.3 Prettier
npm i -D prettier eslint-plugin-prettier eslint-config-prettier
在项目下新建.prettierrc.js ,详细配置如下:
module.exports = {
env: {
browser: true,
node: true,
es6: true,
jest: true,
commonjs: true,
},
extends: ['eslint:recommended', 'plugin:prettier/recommended', 'plugin:vue/essential'],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true,
},
parser: 'babel-eslint',
},
plugins: ['vue', 'prettier'],
rules: {
'prettier/prettier': 2,
/**
* 禁止使用debugger
**/
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
/**
* 禁止使用console
**/
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
/**
* 禁止使用 alert
*/
'no-alert': process.env.NODE_ENV === 'production' ? 'error' : 'off',
/**
* 禁止使用tab
**/
'no-tabs': 'off',
/**
* 首行缩进
*/
indent: 'off',
/**
* 禁止或强制在代码块中开括号前和闭括号后有空格
*/
'block-spacing': 'error',
/**
* 禁止出现未使用过的变量
*/
'no-unused-vars': 'error',
/**
* 在“function”定义的左括号前强制使用一致的间距
*/
'space-before-function-paren': 'off',
/**
* 禁止空格和 tab 的混合缩进
*/
'no-mixed-spaces-and-tabs': 'error',
/**
* 禁止条件表达式中出现赋值操作符
*/
'no-cond-assign': 'error',
/**
* 禁止对象字面量中出现重复的 key
*/
'no-dupe-keys': 'error',
/**
* 数组的方法除了 forEach 之外,回调函数必须有返回值
*/
'array-callback-return': 'error',
/**
* 箭头函数体必须由大括号包裹
* @reason 代码格式问题,最好由 Prettier 解决
*/
'arrow-body-style': 'error',
/**
* 在箭头函数中的箭头前后强制保持一致的间距
*/
'arrow-spacing': [2, { before: true, after: true }],
/**
* 将 var 定义的变量视为块作用域,禁止在块外使用
* @reason 已经禁止使用 var 了
*/
'block-scoped-var': 'error',
/**
* 变量名必须是 camelCase 风格的
* @reason 很多 api 或文件名都不是 camelCase 风格的
*/
camelcase: 'error',
/**
* switch 语句必须有 default
*/
'default-case': 'error',
/**
* switch 语句中的 default 必须在最后
*/
'default-case-last': 'error',
/**
* 必须使用 === 或 !==,禁止使用 == 或 !=
*/
eqeqeq: 'off',
/**
* 属性使用双引号
*/
'jsx-quotes': ['error', 'prefer-double'],
/**
* 单行注释必须写在上一行
*/
'line-comment-position': 'error',
'max-depth': ['error', 5],
/**
* 限制一个文件最多的行数
*/
'max-lines': 'off',
/**
* new 后面的类名必须首字母大写
*/
'new-cap': [
'error',
{
newIsCap: true,
capIsNew: false,
properties: true,
},
],
/**
* 禁止对使用 const 定义的常量重新赋值
*/
'no-const-assign': 'error',
/**
* 禁止解构赋值时出现同样名字的的重命名,比如 let { foo: foo } = bar;
*/
'no-useless-rename': 'error',
/**
* 禁止没必要的 return
*/
'no-useless-return': 'error',
/**
* 禁止使用 var
*/
'no-var': 'error',
/**
* 禁止变量申明时用逗号一次申明多个
*/
'one-var': ['error', 'never'],
/**
* 使用分号
*/
semi: ['error', 'never'],
'vue/camelcase': 'error',
/**
* 修复 no-unused-vars 不检查 jsx 的问题
*/
'vue/jsx-uses-vars': 'error',
/**
* 组件名称必须和文件名一致
*/
'vue/match-component-file-name': 'off',
/**
* 禁止出现重复的属性
*/
'vue/no-duplicate-attributes': [
'error',
{
allowCoexistClass: false,
allowCoexistStyle: false,
},
],
/**
* 禁止修改组件的 props
*/
'vue/no-mutating-props': 'error',
/**
* 禁止出现语法错误
*/
'vue/no-parsing-error': 'error',
/**
* 组件的 name 属性静止使用保留字
*/
'vue/no-reserved-component-names': 'error',
/**
* 禁止覆盖保留字
*/
'vue/no-reserved-keys': 'error',
/**
* 禁止在计算属性中对属性修改
*/
'vue/no-side-effects-in-computed-properties': 'error',
/**
* 禁止 <template> 使用 key 属性
*/
'vue/no-template-key': 'error',
/**
* 模版中的变量名禁止与前一个作用域重名
*/
'vue/no-template-shadow': 'error',
/**
* 禁止使用未注册的组件
*/
'vue/no-unregistered-components': 'off',
/**
* 当你的 vue 版本较老时,禁用还未支持的语法
*/
'vue/no-unsupported-features': 'error',
/**
* 禁止定义在 components 中的组件未使用
*/
'vue/no-unused-components': 'error',
/**
* v-for 指令的元素必须有 v-bind:key
*/
'vue/require-v-for-key': 'error',
/**
* 禁止属性定义了却未使用
*/
'vue/no-unused-properties': 'error',
/**
* 模版中已定义的变量必须使用
*/
'vue/no-unused-vars': 'error',
/**
* 禁止在同一个元素上使用 v-if 和 v-for 指令
*/
'vue/no-use-v-if-with-v-for': 'error',
/**
* props 必须用驼峰式
*/
'vue/prop-name-casing': 'error',
/**
* 计算属性必须有返回值
*/
'vue/return-in-computed-property': 'error',
/**
* vue 组件名称必须是多次,例如GoodDetail,不能是detail
*/
'vue/multi-word-component-names': 0,
},
}
1.4 stylelint
安装依赖
npm i -D stylelint stylelint-config-standard stylelint-less stylelint-order stylelint-webpack-plugin
webpack配置
const StylelintPlugin = require('stylelint-webpack-plugin');
plugins: [
new StylelintPlugin({
files: ['**/*.{html,vue,css,less}'],
fix: false,
cache: true,
failOnError: false
})
]
在项目根目录新建.stylelintrc.js文件,初步配置如下
module.exports = {
defaultSeverity: 'error',
extends: ['stylelint-config-standard'],
plugins: ["stylelint-order",'stylelint-less'],
rules: {
// 不要使用已被 autoprefixer 支持的浏览器前缀
'media-feature-name-no-vendor-prefix': true,
'at-rule-no-vendor-prefix': true,
'selector-no-vendor-prefix': true,
'property-no-vendor-prefix': true,
'value-no-vendor-prefix': true,
"length-zero-no-unit": true,
// 最多允许嵌套20层,去掉默认的最多2层
'max-nesting-depth': 20,
// 颜色值要小写
'color-hex-case': 'lower',
// 颜色值能短则短
'color-hex-length': 'short',
// 不能用important
'declaration-no-important': true,
},
};
在项目的package.json中加入以下的配置
"lint-staged": {
"*.{html,vue,css,less}": [
"stylelint --fix",
"git add"
]
}
二、命名规范
目前我们常用的命名方式是三种命名方式,camelCase(驼峰命名法) 、PascalCase(俗称大驼峰命名法)、kebab-case(连字符分隔命名)
- 文件夹夹使用驼峰命名
- 文件名组件的文件名使用大驼峰命名(PascalCase.vue),其它使用小驼峰命名(camelCase.js/ camelCase.css)
- 图片、资源使用全小写下划线连接命名(min_jquery.js)
- css 类名使用 中划线连字符分隔命名 (kebab-case)
- js 中的构造函数/类 使用驼峰命名(PascalCase)
- 方法和属性使用小驼峰命名(camelCase)
- 枚举性质的常量使用全大写下划线分隔
三、Git 规范
3.1 Git 分支规范
- 分支命名
// 第一个标识分支类型 feature 开发 fix 修复问题 hot 线上问题修复hotfix
// 第二个标识版本迭代时间点,比如某个里程碑时间节点
// 第三个标识 功能点英文名
feature/20220217/project_management
- 分支管理
目前我们项目都是在dev开发和维护,以后会有uat测试环境、pre预发布环境、及prod正式环境,后期我们再制定具体的发布流程,鉴于目前人员增多,单维护dev分支风险较高,如果dev分支被污染或者误操作,代码丢失的风险较大,所以建议开始维护master分支,并且dev分支指定具体的负责人来合并代码和发布,保证dev环境的稳定性,开发按某个周期迭代拉开发分支
3.2 Git 提交规范
约定式规范,提交的说明结构如下:
<type>[optional scope]: <description> // <类型>[可选 范围]: <描述>
[optional body] // [可选 正文]
[optional footer(s)] // [可选 脚注]
在项目的package.json中加入以下的配置
"config": {
"ghooks": {
"pre-commit": "lint-staged",
"commit-msg": "validate-commit-msg"
},
"validate-commit-msg": {
"types": [
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
"revert"
],
"scope": {
"required": false,
"allowed": [
"*"
],
"validate": false,
"multiple": false
},
"warnOnFail": false,
"maxSubjectLength": 100,
"subjectPattern": ".+",
"subjectPatternErrorMsg": "subject does not match subject pattern!",
"helpMessage": "",
"autoFix": false
},
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
},
"lint-staged": {
"src/**/**.{js,vue}": [
"eslint --fix",
"git add"
]
}
},
配置说明:
我们利用ghooks ,链接git的提交过程中去触发某些事项,ghooks就是git 钩子,pre-commit就是在commit之前触发lint-staged命令,commit-msg 就是在commit的时候会去触发validate-commit-msg命令,执行validate-commit-msg之后会去校验配置项的事项,比如提交的type, 代码格式是否符合规范等信息
关键包:
"devDependencies": {
"ghooks": "^2.0.4",
"lint-staged": "^12.3.4",
"validate-commit-msg": "^2.14.0",
"commitizen": "^4.2.4",
"cz-conventional-changelog": "^3.3.0",
}
项目使用:
-
先拉取配置最新代码
git pull
-
在项目的根目录即与 .git 文件同级的目录执行npm install 下载配置依赖
-
切到具体的项目比如pisx-web下 执行npm install 下载配置依赖
-
在执行git commit 的时候有两种方式:
方式1: 直接使用git commit 命令,说明格式安装约定规范的格式提交
git commit -m "feat: 组件customSelect修改"
方式2:使用命令交互窗口执行commit操作,使用npm run commit 或者 yarn commit 命令代替git commit 命令
npm run commit
git add .
npm run commit
**使用commitizen命令交互实现提交:**
我们在项目中,如果使用commitizen命令交互的方式提交时,当要执行 git commit 的命令时,用npm run commit || yarn commit 代替 ,会调器选项命令交互
通过方向键控制选择type,整个过程分为以下几步:
Select the type of change that you're committing // 选择要提交的更改类型
What is the scope of this change (e.g. component or file name) // 此更改的范围是什么(例如组件或文件名,此过程非必填,可以按enter键跳过)
Write a short, imperative tense description of the change (max 76 chars) //写一个简短的、命令式的变化描述(最多76个字符)
Provide a longer description of the change // 提供对更改的详细描述,非必必填,可以按enter键跳过
Are there any breaking changes? (y/N) // 有什么突破性的变化吗 可以选择y/N
Describe the breaking changes // 如果选择y,就需要描述这些突破性的变化
Does this change affect any open issues,如果是,带上对应? (y/N) // 这一变化是否会影响任何未决问题?(是/否),这里是描述本次修改是不是解决某个issues,如果是,带上对应issues编号
**主要type:**
```javascript
feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
test:增加测试
chore:构建过程或辅助工具的变动
build:影响构建系统或外部依赖关系的更改(示例范围:gulp、Brocoli、npm)
ci:对CI配置文件和脚本的更改(示例范围:Travis、Circle、BrowserStack、SauceLabs)
chore:不修改src或测试文件的其他更改
revert:恢复以前的提交
提交规范详解:
- 每个提交都必须使用类型字段前缀,它由一个名词构成,诸如
feat
或fix
, 其后接可选的范围字段,可选的!
,以及必要的冒号(英文半角)和空格。 - 当一个提交为应用或类库实现了新功能时,必须使用
feat
类型。 - 当一个提交为应用修复了 bug 时,必须使用
fix
类型。 - 范围字段可以跟随在类型字段后面。范围必须是一个描述某部分代码的名词,并用圆括号包围,例如:
fix(parser):
- 描述字段必须直接跟在 <类型>(范围) 前缀的冒号和空格之后。 描述指的是对代码变更的简短总结,例如: fix: array parsing issue when multiple spaces were contained in string 。
- 在简短描述之后,可以编写较长的提交正文,为代码变更提供额外的上下文信息。正文必须起始于描述字段结束的一个空行后。
- 提交的正文内容自由编写,并可以使用空行分隔不同段落。
- 在正文结束的一个空行之后,可以编写一行或多行脚注。每行脚注都必须包含 一个令牌(token),后面紧跟
:
或#
作为分隔符,后面再紧跟令牌的值(受 git trailer convention 启发)。 - 脚注的令牌必须使用
-
作为连字符,比如Acked-by
(这样有助于 区分脚注和多行正文)。有一种例外情况就是BREAKING CHANGE
,它可以被认为是一个令牌。 - 脚注的值可以包含空格和换行,值的解析过程必须直到下一个脚注的令牌/分隔符出现为止。
- 破坏性变更必须在提交信息中标记出来,要么在 <类型>(范围) 前缀中标记,要么作为脚注的一项。
- 包含在脚注中时,破坏性变更必须包含大写的文本
BREAKING CHANGE
,后面紧跟着冒号、空格,然后是描述,例如: BREAKING CHANGE: environment variables now take precedence over config files 。 - 包含在 <类型>(范围) 前缀时,破坏性变更必须通过把
!
直接放在:
前面标记出来。 如果使用了!
,那么脚注中可以不写BREAKING CHANGE:
, 同时提交信息的描述中应该用来描述破坏性变更。 - 在提交说明中,可以使用
feat
和fix
之外的类型,比如:docs: updated ref docs. 。 - 工具的实现必须不区分大小写地解析构成约定式提交的信息单元,只有
BREAKING CHANGE
必须是大写的。 - BREAKING-CHANGE 作为脚注的令牌时必须是 BREAKING CHANGE 的同义词
四、VUE开发规范
4.1 组件名应该始终是多个单词的,避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。
Vue.component('todo-item', {
// ...
})
4.2 定义prop时,必须指定其类型
props: {
status: {
type: String,
required: true,
validator: function (value) { // 可选
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
4.3 避免把 v-if 和 v-for 同时用在同一个元素上, 使用v-for指令必须指定key属性
<ul v-if="shouldShowUsers">
<li
v-for="user in users"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
4.4 使用module为组件样式设置作用域
<template>
<button :class="[$style.button, $style.buttonClose]">X</button>
</template>
<!-- 使用 CSS Modules -->
<style src="./helloWorld.less" lang="less" module/>
4.5 只应该拥有单个活跃实例的组件应该以 The 前缀命名,以示其唯一性
components/
|- TheHeading.vue
|- TheSidebar.vue
4.6 和父组件紧密耦合的子组件应该以父组件名作为前缀命名
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
4.7 在单文件组件、字符串模板和 JSX 中没有内容的组件应该是自闭合的
<!-- 在单文件组件、字符串模板和 JSX 中 -->
<MyComponent/>
4.8 组件名应该倾向于完整单词而不是缩写
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue
4.9 在声明 prop 的时候,其命名应该始终使用 camelCase,而在模板和 JSX 中应该始终使用 kebab-case
props: {
greetingText: String
}
<WelcomeMessage greeting-text="hi"/>
4.10 多个 attribute 的元素应该分多行撰写,每个 attribute 一行
<MyComponent
foo="a"
bar="b"
baz="c"
/>
4.11 组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法
<!-- 在模板中 -->
{{ normalizedFullName }}
// 复杂表达式已经移入一个计算属性
computed: {
normalizedFullName: function () {
return this.fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}
}
4.12 把复杂计算属性分割为尽可能多的更简单的 property
computed: {
basePrice: function () {
return this.manufactureCost / (1 - this.profitMargin)
},
discount: function () {
return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function () {
return this.basePrice - this.discount
}
}
4.13 指令缩写 (用 : 表示 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>
4.14 组件/实例的选项的顺序
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
render
renderError
4.15 元素 attribute 的顺序
is
v-for
v-if
v-else-if
v-else
v-show
v-cloak
v-pre
v-once
id
ref
key
v-model
其它自定义
v-on
v-html
v-text
4.16 组件/实例选项中的空行
props: {
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false
},
label: String,
icon: String
},
computed: {
formattedValue: function () {
// ...
},
inputClasses: function () {
// ...
}
}
4.17 单文件组件的顶级元素的顺序
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>
4.18 如果一组 v-if + v-else 的元素类型相同,使用 key (比如两个 <div> 元素)
<div
v-if="error"
key="search-status"
>
错误:{{ error }}
</div>
<div
v-else
key="search-results"
>
{{ results }}
</div>
4.19 元素选择器避免在 scoped 中出现,在 scoped 样式中,类选择器比元素选择器更好,因为大量使用元素选择器是很慢的
<template>
<button class="btn btn-close">X</button>
</template>
<style scoped>
.btn-close {
background-color: red;
}
</style>
4.20 优先通过 prop 和事件进行父子组件之间的通信,而不是 this.$parent 或变更 prop
Vue.component('TodoItem', {
props: {
todo: {
type: Object,
required: true
}
},
template: `
<input
:value="todo.text"
@input="$emit('input', $event.target.value)"
>
`
})
4.21 优先通过 Vuex 管理全局状态,而不是通过 this.$root 或一个全局事件总线
export default {
state: {
list: []
},
mutations: {
REMOVE_TODO (state, todoId) {
state.list = state.list.filter(todo => todo.id !== todoId)
}
},
actions: {
removeTodo ({ commit, state }, todo) {
commit('REMOVE_TODO', todo.id)
}
}
}
<template>
<span>
{{ todo.text }}
<button @click="removeTodo(todo)">
X
</button>
</span>
</template>
<script>
import { mapActions } from 'vuex'
export default {
props: {
todo: {
type: Object,
required: true
}
},
methods: mapActions(['removeTodo'])
}
</script>
4.22 添加实例 property,以 $ 开头声明 property 变量
Vue.prototype.$appName = 'My App'
五、VUE开发文件目录
src 源码目录
|-- api 所有api接口
|-- assets 静态资源,images、icons、styles等
|-- components 公共组件
|-- config 配置信息
|-- constants 常量信息,项目所有Enum,全局变量等
|-- directives 自定义指令
|-- filters 过滤器,全局工具
|-- datas 模拟数据,临时存放
|-- i18n 国际化文件
|-- layouts 项目排版布局文件
|-- lib 外部引用的插件存放以及修改文件
|-- mock 模拟接口,临时存放
|-- plugins 插件,全局使用
|-- router 路由,统一管理
|-- store vuex,统一管理
|-- themes 自定义样式主题
|-- utils 工具类方法,例如文件上传、下载方法
|-- pages 页面目录,对应路由配置
| |--role role 模块名
| |-- |-- RoleList.vue role 列表页面
网友评论