精通任何技能都是需要时间的,但是往往工作中是不会给你这个时间的,尤其是开发工作。新技术层出不穷,每个项目都可能技术栈不一样。

无法改变环境,那么就只能改变我们自身。如果让公司等你精通再开发,那你只能被淘汰。但如果毫无准备进入开发,项目质量又无从谈起,而且项目也可能失控。而微精通就是框定一个最小范围,快速熟悉完成任务所涉及的内容。今天我就拿 Vue 移动端开发做一个实验。

项目初始化

创建项目

1
2
3
4
5
# 安装 Vue Cli
npm install -g @vue/cli

# 创建一个项目
vue create zhiliao-vant

配置Prettier

1、安装依赖

1
$ yarn add prettier eslint-plugin-prettier eslint-config-prettier -D
  • prettier: Prettier CLI
  • eslint-plugin-prettier: 以 ESLint 插件的形式运行 prettier
  • eslint-config-prettier: 关闭所有不必要或可能与 prettier 的规则冲突的 ESLint 规则。一定要放到最后。

2、配置 .eslintrc.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module.exports = {
root: true,
env: {
node: true,
},
extends: [
'plugin:vue/essential',
'@vue/airbnb',
'plugin:prettier/recommended',
"prettier/vue"
],
parserOptions: {
parser: 'babel-eslint',
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// add your rules
},
};

3、新建 /.prettierrc.js,并写入如下配置

注意: 要不要加分号的原则是领导为大,喜好为小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
module.exports = {
printWidth: 120, // 一行的字符数,如果超过会进行换行,默认为80
tabWidth: 2, // tab缩进大小,默认为2
useTabs: false, // 使用tab缩进,默认false
semi: false, // 使用分号, 默认true
/**
* 行尾逗号,默认none,可选 none|es5|all
* es5 包括es5中的数组、对象
* all 包括函数对象等所有可选
*/
trailingComma: 'es5',
singleQuote: true, // 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号)
/**
* 对象中的空格 默认true
* true: { foo: bar }
* false: {foo: bar}
*/
bracketSpacing: true,
/**
* JSX标签闭合位置 默认false
* false:
* <div
* className=""
* style={{}}
* >
* true:
* <div
* className=""
* style={{}} >
*/
jsxBracketSameLine: false,
/**
* 箭头函数参数括号 默认avoid 可选 avoid| always
* avoid 能省略括号的时候就省略 例如x => x
* always 总是有括号
*/
arrowParens: 'always',
vueIndentScriptAndStyle: false, // vue 文件 script 和 style 标签缩进,默认false
endOfLine: 'lf', // 强制使用 unix 风格的换行符
}

vscode 配置

新建 /.vscode/settings.json 并写入以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"editor.formatOnSave": false, // 关闭保存时自动格式化,防止与 eslint 冲突
"files.eol": "\n", // 统一默认行尾字符为 LF
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true // 保存时自动修复
},
// 关闭 vetur 验证功能
"vetur.validation.script": false,
"vetur.validation.style": false,
"vetur.validation.template": false,
"vetur.format.enable": false,
// 禁用 prettier 插件,避免与 eslint 冲突,建议删除 vscode-prettier
"prettier.disableLanguages": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"json",
"jsonc"
],
}

注意:如果是团队协作的项目,请删除 .gitignire 中的 .vscode ,将配置加入到代码库。

Format初始代码

1
$ yarn lint

@vue/cli

~/.vuerc

被保存的 preset 将会存在用户的 home 目录下一个名为 .vuerc 的 JSON 文件里。如果你想要修改被保存的 preset/ 选项,可以编辑这个文件。

在项目创建的过程中,你也会被提示选择喜欢的包管理器或使用淘宝 npm 镜像源以更快地安装依赖。这些选择也将会存入 ~/.vuerc。下面是我的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"useTaobaoRegistry": false,
"packageManager": "yarn",
"presets": {
"javascript": {
"useConfigFiles": true,
"plugins": {
"@vue/cli-plugin-babel": {},
"@vue/cli-plugin-router": {
"historyMode": false
},
"@vue/cli-plugin-vuex": {},
"@vue/cli-plugin-eslint": {
"config": "airbnb",
"lintOn": [
"save",
"commit"
]
}
},
"cssPreprocessor": "less"
}
}
}

git hooks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,vue}": [
"vue-cli-service lint",
"git add"
],
"*.{md,json}": [
"prettier --write",
"git add"
]
}
}

常见问题

vue-cli3出现Invalid Host header的解决方案

参考: vue-cli3出现Invalid Host header的解决方案

产生原因

新版的 webpack-dev-server 增加了安全验证,默认检查hostname,如果hostname不是配置内的,将中断访问。

解决方案

vue.config.js进行如下配置:

1
2
3
4
5
module.exports = {
devServer: {
disableHostCheck: true,
},
}

Vant UI

安装依赖

1
$ yarn add vant

按需引入组件

安装 babel-import-plugin

1
$ yarn add babel-plugin-import -D

对于使用 babel7 的用户,可以在 babel.config.js 中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
plugins: [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true,
},
'vant',
],
],
}

接着你可以在代码中直接引入 Vant 组件:

1
2
import { Button } from 'vant';
Vue.use(Button);

配置基于 Rem 的适配方案

Vant 中的样式默认使用px作为单位,如果需要使用rem单位,推荐使用以下两个工具:

1、安装依赖:

1
2
$ yarn add amfe-flexible
$ yarn add postcss-pxtorem -D

2、在根目录新建 postcss.config.js,并写入以下配置:

参考: 设计稿是750px,根元素应该设置75,但是vant转换后好小,要改成35才行使用vue vantUi框架 根字体是37.5 和默认根字体75不一致,导致页面组件样式变小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module.exports = ({ file }) => {
const designWidth = file.dirname.includes('node_modules/vant') ? 37.5 : 75
return {
plugins: {
autoprefixer: {
overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'],
},
'postcss-pxtorem': {
rootValue: designWidth,
propList: ['*', '!border'],
selectorBlackList: ['.ignore', '.hairlines'],
},
},
}
}

注意: 你可以使用 PxPX 来让 postcss-pxtorem 忽略转换,而且这样浏览器也能识别。

3、在 src/main.js 中引入 amfe-flexible

1
2
3
...
import 'amfe-flexible'
...

底部安全区适配

iPhone X 等机型底部存在底部指示条,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。Vant 中部分组件提供了safe-area-inset-bottom属性,设置该属性后,即可在对应的机型上开启适配,如下示例:

1
2
3
4
5
6
7
8
<!-- 在 head 标签中添加 meta 标签,并设置 viewport-fit=cover 值 -->
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, viewport-fit=cover"
/>

<!-- 开启 safe-area-inset-bottom 属性 -->
<van-number-keyboard safe-area-inset-bottom />

配置自定义主题色方案

1、按需引入样式

babel.config.js 中配置按需引入样式源文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
plugins: [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
// 指定样式路径
style: (name) => `${name}/style/less`,
},
'vant',
],
],
};

2、 修改样式变量

1
$ yarn add less less-loader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// vue.config.js
module.exports = {
css: {
loaderOptions: {
less: {
modifyVars: {
// 直接覆盖变量
'text-color': '#111',
'border-color': '#eee',
// 或者可以通过 less 文件覆盖(文件路径为绝对路径)
hack: 'true; @import "your-less-file-path.less";',
},
},
},
},
};

Vant 使用了 Less 对样式进行预处理,并内置了一些样式变量,下面是一些基本的样式变量,所有可用的颜色变量请参考 配置文件

配置基于 Viewport 的适配方案(推荐)

该方案和配置基于 Rem 的适配方案是互斥的,请二选一。

参考: 移动端布局之postcss-px-to-viewport(兼容vant)vue —— 利用 viewport 进行适配

1、安装 postcss-px-to-viewport

1
$ yarn add postcss-px-to-viewport -D

2、配置 postcss.config.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module.exports = ({ file }) => {
const designWidth = file.dirname.includes('node_modules/vant') ? 375 : 750;
return {
plugins: {
autoprefixer: {
// 用来给不同的浏览器自动添加相应前缀,如-webkit-,-moz-等等
overrideBrowserslist: [
'Android 4.1',
'iOS 7.1',
'Chrome > 31',
'ff > 31',
'ie >= 8',
],
},
"postcss-px-to-viewport": {
unitToConvert: "px", // 要转化的单位
viewportWidth: designWidth, // UI设计稿的宽度
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ["*","!border"], // 指定转换的css属性的单位,*代表全部css属性的单位都进行转换
viewportUnit: "vw", // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: "vw", // 指定字体需要转换成的视窗单位,默认vw
selectorBlackList: ['.ignore', '.hairlines'], // 指定不转换为视窗单位的类名
minPixelValue: 1, // 默认值1,小于或等于1px则不进行转换
landscape: false // 是否处理横屏情况
}
}
}
}
  • propList: 当有些属性的单位我们不希望转换的时候,可以添加在数组后面,并在前面加上!号,如propList: ["*","!border"],这表示:所有css属性的属性的单位都进行转化,除了border
  • selectorBlackList:转换的黑名单,在黑名单里面的我们可以写入字符串,只要类名包含有这个字符串,就不会被匹配。比如selectorBlackList: ['wrap'],它表示形如wrap,my-wrap,wrapper这样的类名的单位,都不会被转换

vue

vue中style scope深度访问新方式(::v-deep)

参考: vue中style scope深度访问新方式(::v-deep)

由于使用 scoped 后,父组件的样式将不会渗透到子组件中。官方引入了 深度作用选择器,来解决这个问题。记得之前使用的是 /deep/,据说这个属性有兼容问题,现在引入了新方式:::v-deep:

1
2
3
4
5
6
7
8
9
10
11
12
#editDoctorAdvice {
.topSearch {
float: left;
margin-right: 10px;
}
&::v-deep .el-input__inner {
padding-right: 6px;
}
.dateTimeClass {
width: 150px;
}
}

参考链接

联系作者

本文首发于杨俊宁的博客

作者微信 赞赏作者