前言 强烈推荐的编辑器 VSCode
为什么选择VSCode进行前端开发
对前端来说,这是一款性感无比的编辑器。咱们团队有大部分人已经在用了,
而且关于VSC 一些提高开发效率的小技巧。我相信已经有不少前端在使用它了。
VSC 本身是基于当前大火的 TS 来写的,所以对于 TS 的支持自然很好;
又是基于 electron 开发,底层 Node.js 对前端来说再熟悉不过了
知乎种草链接:[如何评价 Visual Studio Code?]https://www.zhihu.com/question/29984607/answer/93300215
通用插件
* Auto Close Tag(自动闭合html标签):极其方便快速开发必备
* Auto Rename Tag(自动更改标签):有时候会在开发时候更改标签,此插件能够自动更改对应的标签名
* Debugger for Chrome(模拟谷歌环境来debug):此插件会在项目中生成.vscode文件夹下的launch.json所有配置将在次文件中
* Document This(注释代码):目前来看应该是最受欢迎的注释插件,尤其是注释函数给个赞!!推荐
* Git History、Git Lens、Git Project Manager:这3个就是标准的打包为vscode集成的git服务的。因为本身习惯使用git bash 来操作git的原因所以并未深入研究。不过喜欢方便的小伙伴还是推荐稍微研究下并不难。
* Instellisense(npm插件):必须安装的插件,能够在vscode集成的终端中使用npm。
* Path Autocomplete(路径自动补全):不用是傻子系列。
* JSDoc 是一个 API 文档生成器,你只需要在代码中添加特定格式的注释,它就可以从注释中为你生成 HTML 文档。
* REST Client(可牛逼了):测试http请求的一个插件可牛逼了。这儿不细说,配置不算难但具体实现每个人方法不一样。
* Version Lens(可牛逼了):相信大家在写项目的时候,可能开发1个月后,新的一些依赖module更新了,但是呢我们用着旧的版本想更新啥的。这个插件就是配合package.json来使用的。
beautify(美化插件,为了好看)
* Beautify(美化代码):覆盖面很大。推荐什么代码都有美化!不用写不了代码系列必需品Beautify
* css/sass/scss/less(css美化代码):更好的美化css代码,建议安装。HTML
* Snippets(html5代码片段):同样是个大家都懂得东西,必须的啊谁敢说自己把所有的html标签全给记住了。
* vscode-icons(vscode的icons):简单的小东西就是为你的文件配个icon,好看!安不安装小伙伴自己把。
Vue相关
* Vetur(vscode官方推荐的Vue插件):具体功能挺多自己看官方说明比较详细了
* Vue 2 Snippets(Vue代码片段):不用?你是想v-for、v-if都自己慢慢手打吗???
VSCode 校验&自动格式化&修复
//本人仅供参考
{
"window.zoomLevel": 1,
"workbench.iconTheme": "seti",
"eslint.autoFixOnSave": true,
"javascript.format.insertSpaceBeforeFunctionParenthesis": true, //让函数(名)和后面的括号之间加个空格
"vetur.format.defaultFormatter.html": "js-beautify-html", //格式化.vue中html
"vetur.format.defaultFormatter.js": "vscode-typescript", //让vue中的js按编辑器自带的ts格式进行格式化
"vetur.format.defaultFormatterOptions": {
"js-beautify-html": {
"wrap_attributes": "force-aligned" //属性强制折行对齐
}
},
"eslint.validate": [ //开启对.vue文件中错误的检查
"javascript",
"javascriptreact",
{
"language": "html",
"autoFix": true
},
{
"language": "vue",
"autoFix": true
}
],
"[javascript]": {
"editor.defaultFormatter": "HookyQR.beautify"
},
"explorer.confirmDelete": false,
"[less]": {
"editor.defaultFormatter": "HookyQR.beautify"
},
"[json]": {
"editor.defaultFormatter": "HookyQR.beautify"
},
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"vsicons.dontShowNewVersionMessage": true,
"explorer.confirmDragAndDrop": false,
"diffEditor.ignoreTrimWhitespace": true,
"vetur.format.defaultFormatter.ts": "vscode-typescript",
"editor.renderWhitespace": "all",
"editor.renderControlCharacters": false,
"workbench.colorTheme": "Vue Theme",
"editor.tabSize": 2,
"javascript.updateImportsOnFileMove.enabled": "always",
"[html]": {
"editor.defaultFormatter": "HookyQR.beautify"
},
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"prettier.semi": false, //去掉代码结尾的分号
"prettier.singleQuote": true, //使用单引号替代双引号
}
Vue项目开发规范 [Vue-cli Vue Eslint Webpack]
安装一个vue项目 基于vue
vue-cli3+、vue-cli4+ 相比于 vue-cli2+
最大的改变就是将约定俗称的配置,全部公共化了,也就是做了一次二次封装。这样的好处在于,我们不必要在繁多的配置代码中寻找需要的配置。
现在最新的版本应该是4.1.2 但是内容基本和cli3.x 一致。所以直接安装就可以。
不过还是建议看一下两个版本的修改的地方。
传送门:https://cli.vuejs.org/migrating-from-v3/
安装完cli后 执行创建项目命令
vue create test-project
建议选择手动配置
创建一个适合自己项目需要的一些配置文件
eslint 建议选择standard标准风格,这个风格也是目前使用人数最多的。
standard风格的规则,传送门: github.com/standard/st…
其实在cli3.x之后完全可以开启Git Hook。这样的话,如果git commit 之前不通过则不允许代码提交。
生成的文件目录
组件开发
删除无用目录或文件,保持项目目录及代码结构清晰
例如如果在init 项目的时候 创建了单元测试文件夹,无用的时候可以将其删除。
没有什么以后可能用的️着的情 况
无用的注释代码 旧的逻辑、样式、没有必要的console可以删除。并不一定要完全以来webpack 和 eslint 去配置
覆盖默认样式【样式重置 reset】
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
html, body {
width: 100%;
height: 100%;
overflow: auto;
margin: 0;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
}
使用mixin样式工具
@baseColor: #FF6300;
@bgColor: #FFFFFF;
@font-family: PingFangSC-Regular, PingFangSC;
@font-family-1: PingFang-SC-Bold, PingFang-SC;
@font-family-2: PingFangSC-Medium, PingFangSC;
@font-family-3: PingFangSC-Light, PingFangSC;
// .font-mixin(58px, @font-family-2, 500);
.font-mixin(@size, @family, @weight) {
font-size: @size;
font-family: @family;
font-weight: @weight;
}
//isurl('hetao101.com')
//ispixel(20px)
//iscolor(#fff)
//isstring('11')
//isnumber(1)
//ispercentage(20%)
.mixin-bc(@url) when (isurl(@url)) {
background: @url no-repeat;
background-position: center 0px;
background-size: 152px 152px;
}
项目解构重构【readme文件的更新】
项目结构构建过程中,应该不断维护readme文档,并且建立项目结构版本,如:1.0.0,并且应该标注如下几点:
结构中新建与改动过程的动作说明
项目结构版本信息
文件夹命名规范
一般目录命名采用lowercase方式,,目录由多个单词组件则利用"-"连接,如:
router,
store,
components,
store/modules,
utils/plugin
views中路由视图目录采用大驼峰形式命名,如:
views/Algorithms
views/Events
views/Monitor
代码编写规范
良好的代码编写规范可以大幅度提高项目开发效率,增加代码的可读性/可维护性/可测试性,减少开发/重构等场景的复杂耗时程度。
我主要从 3 个方面来做一些编码效率上的改进
升级你的 vue-cli 减少 webpack 配置的成本
使用 less、stylus,利用里面函数、mixins、变量提升 css 文件的复用
使用 pug,减少 html 的代码编写量
组件以驼峰命名
组件名应该始终是多个单词的,根组件 App 以及 <transition>、<component> 之类的 Vue 内置组件除外。
这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。
Vue.component('todo-item', {
// ...
})
export default {
name: 'TodoItem',
// ...
}
<template>
<my-components></my-components>
</template>
<script>
import myComponents from './myComponents.vue'
export default {
components: {
myComponents
}
}
</script>
组件按需加载
三种按需加载的方法vue异步resolve => require()、ES6提案的import()、webpack提供的require.ensure()
推荐使用第二种。
// 下面2行代码,没有指定webpackChunkName,每个组件打包成一个js文件。
const ImportFuncDemo1 = () => import('../components/ImportFuncDemo1')
const ImportFuncDemo2 = () => import('../components/ImportFuncDemo2')
// 下面2行代码,指定了相同的webpackChunkName,会合并打包成一个js文件。
// const ImportFuncDemo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo')
// const ImportFuncDemo2 = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo2')
export default new Router({
routes: [
{
path: '/importfuncdemo1',
name: 'ImportFuncDemo1',
component: ImportFuncDemo1
},
{
path: '/importfuncdemo2',
name: 'ImportFuncDemo2',
component: ImportFuncDemo2
}
]
})
组件数据
Vue.component('some-comp', {
data: function () {
return {
foo: 'bar'
}
}
})
// In a .vue file
export default {
data () {
return {
foo: 'bar'
}
}
}
Props定义
props: {
status: String
}
// 更好的做法!
props: {
status: {
type: String,
required: true,
validator: function (value) {
return [
'syncing',
'synced',
'version-conflict',
'error'
].indexOf(value) !== -1
}
}
}
为 v-for 设置键值
<ul>
<li
v-for="todo in todos"
:key="todo.id"
>
{{ todo.text }}
</li>
</ul>
避免 v-if 和 v-for 用在一起
<ul v-if="shouldShowUsers">
<li
v-for="user in users"
:key="user.id"
>
{{ user.name }}
</li>
</ul>
methods 里面一个方法尽量只做一件事,增强可读性和维护行。
setLastNumber () {
setInterval(() => {
this.lastNumber = this.lastNumber > 1 ? this.lastNumber - 1 : 100
}, 1000)
},
setLastTime () {
let endT = Number(window.localStorage.getItem('httt'))
const currentT = new Date().getTime()
if (!endT || currentT >= endT) {
endT = new Date().getTime() + 3 * 60 * 60 * 1000
window.localStorage.setItem('httt', endT)
}
getCountDownTime({
endTime: endT,
timeCb: t => {
this.lastTime = t
},
endCb: () => {
this.setLastTime()
}
})
}
为组件样式设置作用域
<!-- 使用 `scoped` 特性 -->
<style scoped>
.button {
border: none;
border-radius: 2px;
}
.button-close {
background-color: red;
}
</style>
组件引用
import myComponentsA from './myComponentsA.vue'
import myComponentsB from './myComponentsB.vue'
import myComponentsC from './myComponentsC.vue'
import myComponentsD from './myComponentsD.vue'
export default {
components: {
myComponentsA,
myComponentsB,
myComponentsC,
myComponentsD,
}
}
事件
<!-- 不建议 -->
<a v-on:click="pass()">pass</a>
<!-- 推荐 -->
<a @click="pass">pass</a>
组件拆分(复用)
components/
|- TodoList.js
|- TodoItem.js
components/
|- TodoList.vue
|- TodoItem.vue
紧密耦合的组件名
反例
components/
|- TodoList.vue
|- TodoItem.vue
|- TodoButton.vue
components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue
components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue
完整的组件名
反例
components/
|- SdSettings.vue
|- UProfOpts.vue
好例子
components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue
多个特性的元素
反例
<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<MyComponent foo="a" bar="b" baz="c"/>
好例子
<img
src="https://vuejs.org/images/logo.png"
alt="Vue Logo"
>
<MyComponent
foo="a"
bar="b"
baz="c"
/>
模版中的简单表达式 计算属性
不建议
{{
fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}}
建议
<!-- 在模板中 -->
{{ normalizedFullName }}
// 复杂表达式已经移入一个计算属性
computed: {
normalizedFullName: function () {
return this.fullName.split(' ').map(function (word) {
return word[0].toUpperCase() + word.slice(1)
}).join(' ')
}
}
反例
computed: {
price: function () {
var basePrice = this.manufactureCost / (1 - this.profitMargin)
return (
basePrice -
basePrice * (this.discountPercent || 0)
)
}
}
好例子
computed: {
basePrice: function () {
return this.manufactureCost / (1 - this.profitMargin)
},
discount: function () {
return this.basePrice * (this.discountPercent || 0)
},
finalPrice: function () {
return this.basePrice - this.discount
}
}
指令缩写
指令缩写 (用 : 表示 v-bind: 、用 @ 表示 v-on: 和用 # 表示 v-slot:) 应该要么都用要么都不用。
<input
@input="onInput"
@focus="onFocus"
>
<input
:value="newTodoText"
:placeholder="newTodoInstructions"
>
vuex之store拆分即多模块状态管理
将store进行拆分,有利于我们更好的管理项目中的状态,以及使我们的项目维护更加加单高效。各个模块之间的开发互相不影响。
vuex使用尽量用modules把store分成模块,且为避免命名冲突问题建议开启module命名空间,目录如下:
|-store
|-index.js
|-modules
|-moduleA
|-moduleB
// mod1.js
export default {
state:{},
mutatons:{},
actions:{},
getters:{}
}
// mod2.js
export default {
state:{},
mutatons:{},
actions:{},
getters:{}
}
// 然后在将几个mod合并到store中去:
import vue from 'vue'
import vuex from 'vuex'
import mod1 from './mod1.js'
import mod2 from './mod2.js'
vue.use(vuex);
export default new vuex.Store({
modules:{
mod1:mod1,
mod2:mod1
}
});
Eslint .eslintrc.js其实希望不要用到rules这个规则。
文件配置 [环境、全局变量、解析器、规则]
module.exports = {
root: true,
env: {
browser: true
},
'extends': [
'plugin:vue/essential',
'@vue/standard'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
parserOptions: {
parser: 'babel-eslint'
},
globals: {
'sa': false,
'pingpp_ui': false,
'fundebug': false,
'gdt': true,
'meteor': true,
'utq': true
},
}
rules规则配置
.eslintrc.js文件是cli抛给开发者的配置eslint的文件入口。养成良好的开发习惯,并且按照standard风格开发,这一块其实完全不需要配置。也不建议配置
按照一种约定俗成的规则开发项目,也别是某个项目多人都介入的情况下,一致的开发规则能够减少冗余代码的堆积、提升工作效率。
{
"rules" : {
// 定义对象的set存取器属性时,强制定义get
"accessor-pairs": 2,
// 指定数组的元素之间要以空格隔开(,后面), never参数:[ 之前和 ] 之后不能带空格,always参数:[ 之前和 ] 之后必须带空格
"array-bracket-spacing": [2, "never"],
// 在块级作用域外访问块内定义的变量是否报错提示
"block-scoped-var": 0,
// if while function 后面的{必须与if在同一行,java风格。
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
// 双峰驼命名格式
"camelcase": 2,
// 数组和对象键值对最后一个逗号, never参数:不能带末尾的逗号, always参数:必须带末尾的逗号,
// always-multiline:多行模式必须带逗号,单行模式不能带逗号
"comma-dangle": [2, "never"],
// 控制逗号前后的空格
"comma-spacing": [2, { "before": false, "after": true }],
// 控制逗号在行尾出现还是在行首出现
// http://eslint.org/docs/rules/comma-style
"comma-style": [2, "last"],
// 圈复杂度
"complexity": [2,9],
// 以方括号取对象属性时,[ 后面和 ] 前面是否需要空格, 可选参数 never, always
"computed-property-spacing": [2,"never"],
// 强制方法必须返回值,TypeScript强类型,不配置
"consistent-return": 0,
// 用于指统一在回调函数中指向this的变量名,箭头函数中的this已经可以指向外层调用者,应该没卵用了
// e.g [0,"that"] 指定只能 var that = this. that不能指向其他任何值,this也不能赋值给that以外的其他值
"consistent-this": 0,
// 强制在子类构造函数中用super()调用父类构造函数,TypeScrip的编译器也会提示
"constructor-super": 0,
// if else while for do后面的代码块是否需要{ }包围,参数:
// multi 只有块中有多行语句时才需要{ }包围
// multi-line 只有块中有多行语句时才需要{ }包围, 但是块中的执行语句只有一行时,
// 块中的语句只能跟和if语句在同一行。if (foo) foo++; else doSomething();
// multi-or-nest 只有块中有多行语句时才需要{ }包围, 如果块中的执行语句只有一行,执行语句可以零另起一行也可以跟在if语句后面
// [2, "multi", "consistent"] 保持前后语句的{ }一致
// default: [2, "all"] 全都需要{ }包围
"curly": [2, "all"],
// switch语句强制default分支,也可添加 // no default 注释取消此次警告
"default-case": 2,
// 强制object.key 中 . 的位置,参数:
// property,'.'号应与属性在同一行
// object, '.' 号应与对象名在同一行
"dot-location": [2, "property"],
// 强制使用.号取属性
// 参数: allowKeywords:true 使用保留字做属性名时,只能使用.方式取属性
// false 使用保留字做属性名时, 只能使用[]方式取属性 e.g [2, {"allowKeywords": false}]
// allowPattern: 当属性名匹配提供的正则表达式时,允许使用[]方式取值,否则只能用.号取值 e.g [2, {"allowPattern": "^[a-z]+(_[a-z]+)+$"}]
"dot-notation": [2, {"allowKeywords": true}],
// 文件末尾强制换行
"eol-last": 2,
// 使用 === 替代 ==
"eqeqeq": [2, "allow-null"],
// 方法表达式是否需要命名
"func-names": 0,
// 方法定义风格,参数:
// declaration: 强制使用方法声明的方式,function f(){} e.g [2, "declaration"]
// expression:强制使用方法表达式的方式,var f = function() {} e.g [2, "expression"]
// allowArrowFunctions: declaration风格中允许箭头函数。 e.g [2, "declaration", { "allowArrowFunctions": true }]
"func-style": 0,
"no-alert": 0,//禁止使用alert confirm prompt
"no-array-constructor": 2,//禁止使用数组构造器
"no-bitwise": 0,//禁止使用按位运算符
"no-caller": 1,//禁止使用arguments.caller或arguments.callee
"no-catch-shadow": 2,//禁止catch子句参数与外部作用域变量同名
"no-class-assign": 2,//禁止给类赋值
"no-cond-assign": 2,//禁止在条件表达式中使用赋值语句
"no-console": 2,//禁止使用console
"no-const-assign": 2,//禁止修改const声明的变量
"no-constant-condition": 2,//禁止在条件中使用常量表达式 if(true) if(1)
"no-continue": 0,//禁止使用continue
"no-control-regex": 2,//禁止在正则表达式中使用控制字符
"no-debugger": 2,//禁止使用debugger
"no-delete-var": 2,//不能对var声明的变量使用delete操作符
"no-div-regex": 1,//不能使用看起来像除法的正则表达式/=foo/
"no-dupe-keys": 2,//在创建对象字面量时不允许键重复 {a:1,a:1}
"no-dupe-args": 2,//函数参数不能重复
"no-duplicate-case": 2,//switch中的case标签不能重复
"no-else-return": 2,//如果if语句里面有return,后面不能跟else语句
"no-empty": 2,//块语句中的内容不能为空
"no-empty-character-class": 2,//正则表达式中的[]内容不能为空
"no-empty-label": 2,//禁止使用空label
"no-eq-null": 2,//禁止对null使用==或!=运算符
"no-eval": 1,//禁止使用eval
"no-ex-assign": 2,//禁止给catch语句中的异常参数赋值
"no-extend-native": 2,//禁止扩展native对象
"no-extra-bind": 2,//禁止不必要的函数绑定
"no-extra-boolean-cast": 2,//禁止不必要的bool转换
"no-extra-parens": 2,//禁止非必要的括号
"no-extra-semi": 2,//禁止多余的冒号
"no-fallthrough": 1,//禁止switch穿透
"no-floating-decimal": 2,//禁止省略浮点数中的0 .5 3.
"no-func-assign": 2,//禁止重复的函数声明
"no-implicit-coercion": 1,//禁止隐式转换
"no-implied-eval": 2,//禁止使用隐式eval
"no-inline-comments": 0,//禁止行内备注
"no-inner-declarations": [2, "functions"],//禁止在块语句中使用声明(变量或函数)
"no-invalid-regexp": 2,//禁止无效的正则表达式
"no-invalid-this": 2,//禁止无效的this,只能用在构造器,类,对象字面量
"no-irregular-whitespace": 2,//不能有不规则的空格
"no-iterator": 2,//禁止使用__iterator__ 属性
"no-label-var": 2,//label名不能与var声明的变量名相同
"no-labels": 2,//禁止标签声明
"no-lone-blocks": 2,//禁止不必要的嵌套块
"no-lonely-if": 2,//禁止else语句内只有if语句
"no-loop-func": 1,//禁止在循环中使用函数(如果没有引用外部变量不形成闭包就可以)
"no-mixed-requires": [0, false],//声明时不能混用声明类型
"no-mixed-spaces-and-tabs": [2, false],//禁止混用tab和空格
"linebreak-style": [0, "windows"],//换行风格
"no-multi-spaces": 1,//不能用多余的空格
"no-multi-str": 2,//字符串不能用\换行
"no-multiple-empty-lines": [1, {"max": 2}],//空行最多不能超过2行
"no-native-reassign": 2,//不能重写native对象
"no-negated-in-lhs": 2,//in 操作符的左边不能有!
"no-nested-ternary": 0,//禁止使用嵌套的三目运算
"no-new": 1,//禁止在使用new构造一个实例后不赋值
"no-new-func": 1,//禁止使用new Function
"no-new-object": 2,//禁止使用new Object()
"no-new-require": 2,//禁止使用new require
"no-new-wrappers": 2,//禁止使用new创建包装实例,new String new Boolean new Number
"no-obj-calls": 2,//不能调用内置的全局对象,比如Math() JSON()
"no-octal": 2,//禁止使用八进制数字
"no-octal-escape": 2,//禁止使用八进制转义序列
"no-param-reassign": 2,//禁止给参数重新赋值
"no-path-concat": 0,//node中不能使用__dirname或__filename做路径拼接
"no-plusplus": 0,//禁止使用++,--
"no-process-env": 0,//禁止使用process.env
"no-process-exit": 0,//禁止使用process.exit()
"no-proto": 2,//禁止使用__proto__属性
"no-redeclare": 2,//禁止重复声明变量
"no-regex-spaces": 2,//禁止在正则表达式字面量中使用多个空格 /foo bar/
"no-restricted-modules": 0,//如果禁用了指定模块,使用就会报错
"no-return-assign": 1,//return 语句中不能有赋值表达式
"no-script-url": 0,//禁止使用javascript:void(0)
"no-self-compare": 2,//不能比较自身
"no-sequences": 0,//禁止使用逗号运算符
"no-shadow": 2,//外部作用域中的变量不能与它所包含的作用域中的变量或参数同名
"no-shadow-restricted-names": 2,//严格模式中规定的限制标识符不能作为声明时的变量名使用
"no-spaced-func": 2,//函数调用时 函数名与()之间不能有空格
"no-sparse-arrays": 2,//禁止稀疏数组, [1,,2]
"no-sync": 0,//nodejs 禁止同步方法
"no-ternary": 0,//禁止使用三目运算符
"no-trailing-spaces": 1,//一行结束后面不要有空格
"no-this-before-super": 0,//在调用super()之前不能使用this或super
"no-throw-literal": 2,//禁止抛出字面量错误 throw "error";
"no-undef": 1,//不能有未定义的变量
"no-undef-init": 2,//变量初始化时不能直接给它赋值为undefined
"no-undefined": 2,//不能使用undefined
"no-unexpected-multiline": 2,//避免多行表达式
"no-underscore-dangle": 1,//标识符不能以_开头或结尾
"no-unneeded-ternary": 2,//禁止不必要的嵌套 var isYes = answer === 1 ? true : false;
"no-unreachable": 2,//不能有无法执行的代码
"no-unused-expressions": 2,//禁止无用的表达式
"no-unused-vars": [2, {"vars": "all", "args": "after-used"}],//不能有声明后未被使用的变量或参数
"no-use-before-define": 2,//未定义前不能使用
"no-useless-call": 2,//禁止不必要的call和apply
"no-void": 2,//禁用void操作符
"no-var": 0,//禁用var,用let和const代替
"no-warning-comments": [1, { "terms": ["todo", "fixme", "xxx"], "location": "start" }],//不能有警告备注
"no-with": 2,//禁用with
"array-bracket-spacing": [2, "never"],//是否允许非空数组里面有多余的空格
"arrow-parens": 0,//箭头函数用小括号括起来
"arrow-spacing": 0,//=>的前/后括号
"accessor-pairs": 0,//在对象中使用getter/setter
"block-scoped-var": 0,//块语句中使用var
"brace-style": [1, "1tbs"],//大括号风格
"callback-return": 1,//避免多次调用回调什么的
"camelcase": 2,//强制驼峰法命名
"comma-dangle": [2, "never"],//对象字面量项尾不能有逗号
"comma-spacing": 0,//逗号前后的空格
"comma-style": [2, "last"],//逗号风格,换行时在行首还是行尾
"complexity": [0, 11],//循环复杂度
"computed-property-spacing": [0, "never"],//是否允许计算后的键名什么的
"consistent-return": 0,//return 后面是否允许省略
"consistent-this": [2, "that"],//this别名
"constructor-super": 0,//非派生类不能调用super,派生类必须调用super
"curly": [2, "all"],//必须使用 if(){} 中的{}
"default-case": 2,//switch语句最后必须有default
"dot-location": 0,//对象访问符的位置,换行的时候在行首还是行尾
"dot-notation": [0, { "allowKeywords": true }],//避免不必要的方括号
"eol-last": 0,//文件以单一的换行符结束
"eqeqeq": 2,//必须使用全等
"func-names": 0,//函数表达式必须有名字
"func-style": [0, "declaration"],//函数风格,规定只能使用函数声明/函数表达式
"generator-star-spacing": 0,//生成器函数*的前后空格
"guard-for-in": 0,//for in循环要用if语句过滤
"handle-callback-err": 0,//nodejs 处理错误
"id-length": 0,//变量名长度
"indent": [2, 4],//缩进风格
"init-declarations": 0,//声明时必须赋初值
"key-spacing": [0, { "beforeColon": false, "afterColon": true }],//对象字面量中冒号的前后空格
"lines-around-comment": 0,//行前/行后备注
"max-depth": [0, 4],//嵌套块深度
"max-len": [0, 80, 4],//字符串最大长度
"max-nested-callbacks": [0, 2],//回调嵌套深度
"max-params": [0, 3],//函数最多只能有3个参数
"max-statements": [0, 10],//函数内最多有几个声明
"new-cap": 2,//函数名首行大写必须使用new方式调用,首行小写必须用不带new方式调用
"new-parens": 2,//new时必须加小括号
"newline-after-var": 2,//变量声明后是否需要空一行
"object-curly-spacing": [0, "never"],//大括号内是否允许不必要的空格
"object-shorthand": 0,//强制对象字面量缩写语法
"one-var": 1,//连续声明
"operator-assignment": [0, "always"],//赋值运算符 += -=什么的
"operator-linebreak": [2, "after"],//换行时运算符在行尾还是行首
"padded-blocks": 0,//块语句内行首行尾是否要空行
"prefer-const": 0,//首选const
"prefer-spread": 0,//首选展开运算
"prefer-reflect": 0,//首选Reflect的方法
"quotes": [1, "single"],//引号类型 `` "" ''
"quote-props":[2, "always"],//对象字面量中的属性名是否强制双引号
"radix": 2,//parseInt必须指定第二个参数
"id-match": 0,//命名检测
"require-yield": 0,//生成器函数必须有yield
"semi": [2, "always"],//语句强制分号结尾
"semi-spacing": [0, {"before": false, "after": true}],//分号前后空格
"sort-vars": 0,//变量声明时排序
"space-after-keywords": [0, "always"],//关键字后面是否要空一格
"space-before-blocks": [0, "always"],//不以新行开始的块{前面要不要有空格
"space-before-function-paren": [0, "always"],//函数定义时括号前面要不要有空格
"space-in-parens": [0, "never"],//小括号里面要不要有空格
"space-infix-ops": 0,//中缀操作符周围要不要有空格
"space-return-throw-case": 2,//return throw case后面要不要加空格
"space-unary-ops": [0, { "words": true, "nonwords": false }],//一元运算符的前/后要不要加空格
"spaced-comment": 0,//注释风格不要有空格什么的
"strict": 2,//使用严格模式
"use-isnan": 2,//禁止比较时使用NaN,只能用isNaN()
"valid-jsdoc": 0,//jsdoc规则
"valid-typeof": 2,//必须使用合法的typeof的值
"vars-on-top": 2,//var必须放在作用域顶部
"wrap-iife": [2, "inside"],//立即执行函数表达式的小括号风格
"wrap-regex": 0,//正则表达式字面量用小括号包起来
"yoda": [2, "never"]//禁止尤达条件
}
}
.eslintignore
【功能与 .gitignore类似 对某些文件或者文件夹忽略】
/build/
/config/
/dist/
/*.js
/test/unit/coverage/
//不建议
/src/service/
/src/utils/
/src/components/sharelandingpage/
/src/router/
/src/main.js
/src/pages/common/Protocol.vue
浏览器兼容性
兼容的浏览器版本 .browserslistrc
//你会发现有 package.json 文件里的 browserslist 字段 (或一个单独的 .browserslistrc 文件),指定了项目的目标浏览器的范围。
//这个值会被 @babel/preset-env 和 Autoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀
> 1%
last 2 versions
语法兼容 babel.config.js
Vue Cli 3已经开始使用babel.config.js,而不是.babelrc
默认情况下,cli会把 useBuiltIns: 'usage' 传递给 @babel/preset-env,这样它会根据源代码中出现的语言特性自动检测需要的 polyfill
这确保了最终包里 polyfill 数量的最小化。但是如果其中一个依赖需要特殊的 polyfill,默认情况下 Babel 无法将其检测出来。我们可以通过如下三种方式解决此类问题:
* 将依赖添加到 vue.config.js 中的 transpileDependencies 选项// vue.config.js
module.exports = {
// 默认情况下 babel-loader 会忽略所有 node_modules 中的文件。如果你想要通过 Babel 显式转译一个依赖,可以在这个选项中列出来
transpileDependencies: 'glob'
}
// babel.config.js
module.exports = {
presets: [
['@vue/app', {
polyfills:
'es6.promise',
'es6.symbol'
}]
]
}
* 可以使用 @vue/babel-preset-app 的 polyfills 选项预包含所需要的 polyfill
* 使用 useBuiltIns: 'entry' 然后在入口文件添加 import '@babel/polyfill',这种方式的问题就是会增加包的大小
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
移动端样式兼容 postcss.config.js
//咱们项目中普遍通用的移动端兼容的方法。
module.exports = {
plugins: {
'postcss-import': {},
'postcss-url': {},
'postcss-preset-env': {},
'cssnano': {},
// to edit target browsers: use "browserslist" field in package.json
autoprefixer: {},
'postcss-px-to-viewport': {
viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
selectorBlackList: ['.ignore', '.hairlines'], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false // 允许在媒体查询中转换`px`
}
}
}
Webpack 配置
vue cli 3.x之后的版本 webpack的配置默认使用 vue.config.js 中的configureWebpack & chainWebpack
const path = require("path");
const resolve = dir => path.join(__dirname, dir);
//用于生产环境去除多余的css
const PurgecssPlugin = require("purgecss-webpack-plugin");
//全局文件路径
const glob = require("glob-all");
//压缩代码并去掉console
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
//代码打包zip
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
module.exports = {
// 废弃baseUrl 一般运维会配置好的
publicPath: process.env.NODE_ENV === "production" ? "/configtest/" : "/",
//打包的输出目录
outputDir: "dist/configtest",
//保存是校验
lintOnSave: true,
//如果文件等设置
pages: {
index: {
entry: "src/main.js",
template: "public/index.html",
filename: "index.html"
}
},
//静态资源打包路径
assetsDir: "static",
//默认false 可以加快打包
productionSourceMap: false,
//打包后的启动文件
indexPath: "congfigtest.html",
//打包文件是否使用hash
filenameHashing: true,
runtimeCompiler: false,
transpileDependencies: [],
//打包的css路径及命名
css: {
modules: false,
//vue 文件中修改css 不生效 注释掉 extract:true
extract: {
filename: "style/[name].[hash:8].css",
chunkFilename: "style/[name].[hash:8].css"
},
sourceMap: false,
loaderOptions: {
css: {},
less: {
// 向全局less样式传入共享的全局变量
// data: `@import "~assets/less/variables.less";$src: "${process.env.VUE_APP_SRC}";`
},
// postcss 设置
postcss: {
plugins: [
require("postcss-px-to-viewport")({
viewportWidth: 750, // 视窗的宽度,对应的是我们设计稿的宽度,一般是750
viewportHeight: 1334, // 视窗的高度,根据750设备的宽度来指定,一般指定1334,也可以不配置
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
viewportUnit: "vw", // 指定需要转换成的视窗单位,建议使用vw
selectorBlackList: [".ignore", ".hairlines"], // 指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值
mediaQuery: false // 允许在媒体查询中转换`px`
})
]
}
}
},
//webpack 链式配置 默认已经配置好了 node_moudles/@vue
chainWebpack: config => {
// 修复HMR
config.resolve.symlinks(true);
// 修复Lazy loading routes 按需加载的问题,如果没有配置按需加载不需要写,会报错
// config.plugin("html").tap(args => {
// args[0].chunksSortMode = "none";
// return args;
// });
//添加别名
config.resolve.alias
.set("@", resolve("src"))
.set("assets", resolve("src/assets"))
.set("components", resolve("src/components"))
.set("layout", resolve("src/layout"))
.set("base", resolve("src/base"))
.set("static", resolve("src/static"));
// 压缩图片
config.module
.rule("images")
.use("image-webpack-loader")
.loader("image-webpack-loader")
.options({
mozjpeg: { progressive: true, quality: 65 },
optipng: { enabled: false },
pngquant: { quality: "65-90", speed: 4 },
gifsicle: { interlaced: false },
webp: { quality: 75 }
});
},
//webpack 配置
configureWebpack: config => {
const plugins = [];
//去掉不用的css 多余的css
plugins.push(
new PurgecssPlugin({
paths: glob.sync([path.join(__dirname, "./**/*.vue")]),
extractors: [
{
extractor: class Extractor {
static extract(content) {
const validSection = content.replace(
/<style([\s\S]*?)<\/style>+/gim,
""
);
return validSection.match(/[A-Za-z0-9-_:/]+/g) || [];
}
},
extensions: ["html", "vue"]
}
],
whitelist: ["html", "body"],
whitelistPatterns: [/el-.*/],
whitelistPatternsChildren: [/^token/, /^pre/, /^code/]
})
);
//启用代码压缩
plugins.push(
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false,
drop_console: true,
drop_debugger: false,
pure_funcs: ["console.log"] //移除console
}
},
sourceMap: false,
parallel: true
})
),
//代码压缩打包
plugins.push(
new CompressionWebpackPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: productionGzipExtensions,
threshold: 10240,
minRatio: 0.8
})
);
config.plugins = [...config.plugins, ...plugins];
},
parallel: require("os").cpus().length > 1,
pluginOptions: {},
pwa: {},
//设置代理
devServer: {
port: 8080,
host: "0.0.0.0",
https: false,
open: true,
openPage: "about",
hot: true,
disableHostCheck: true,
proxy: {
"/api": {
target: "https://cdn.awenliang.cn",
ws: true,
changeOrigin: true
},
"/foo": {
target: "https://cdn.awenliang.cn",
ws: true,
changeOrigin: true
}
}
}
};