H5
# 移动端适配
1px
等于2个物理像素
安装
lib-flexible
和postcss-plugin-px2rem
npm i lib-flexible -S
npm i postcss-plugin-px2rem -D
- 不必删除
viewport
配置文件
.postcssrc.js
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {},
"postcss-plugin-px2rem": {
rootValue: 75,
// rootValue: 37.5,
unitPrecision: 8,
propWhiteList: [],
propBlackList: [
'box-shadow',
'border-radius'
],
selectorBlackList: [
':root',
'.pc-width',
'activity-info__item-mark'
],
ignoreIdentifier: false,
replace: true,
mediaQuery: false,
minPixelValue: 2
}
}
}
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
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
# Eslint配置
# 基础配置
- vscode插件安装
Vetur
(必安装)、Prettier
(必安装)、Prettier ESLint
(必安装) Vetur
插件配置,文件->首选项->设置->在"用户"tab下搜索vetur.useWorkspaceDependencies
,打钩。作用是配置以工作区配置为主。
// 修改`.vscode/settings.json`配置,搜索 tabSize 或 tabWidth 共4处
{
// 重新设定tabsize
"editor.tabSize": 4,
// 重新设定tabsize
"vetur.format.options.tabSize": 4,
"prettier.tabWidth": 4,
"tabWidth": 4,
}
// 2. 增加`.eslintrc.js`配置
{
"rules": {
// ...
'indent': ['error', 4],
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 详细配置
- 项目跟目录添加文件
.vscode/setting.json
{
// 文件不被覆盖
"workbench.editor.enablePreview": false,
"workbench.startupEditor": "welcomePage",
// 是否自动设置tabsize的选项
"editor.detectIndentation": false,
// 重新设定tabsize
"editor.tabSize": 2,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
// 保存时候自动格式化
"editor.formatOnSave": true,
// 两个选择器中是否换行
"editor.autoIndent": "keep",
// eslint配置
"eslint.format.enable": true,
// 添加 vue 支持
"eslint.validate": [
"javascript",
"vue"
],
// vue文件默认格式化工具或配置
"[vue]": {
"editor.defaultFormatter": "octref.vetur"
},
// js文件默认格式化工具或配置
"[javascript]": {
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
},
// json文件默认格式化工具或配置
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
// vetur插件配置
"vetur.format.defaultFormatter.html": "prettier",
// 重新设定tabsize
"vetur.format.options.tabSize": 2,
// 让vue中的js按prettier-eslint规则进行格式化
"vetur.format.defaultFormatter.js": "prettier-eslint",
"vetur.completion.autoImport": false,
"vetur.format.defaultFormatterOptions": {
// vetur插件引用的prettier配置
"prettier": {
// 一行最多 120 字符
"printWidth": 120,
// 重新设定tabsize
"tabWidth": 2,
// 根据显示样式决定 html 要不要折行
"htmlWhitespaceSensitivity": "ignore",
// 末尾不需要逗号
"trailingComma": "none",
},
"js-beautify-html": {
"wrap_attributes": "force-aligned"
// vue组件中html代码格式化样式
}
},
// prettier插件配置
"prettier.printWidth": 120,
// prettier重新设定tabsize
"prettier.tabWidth": 2,
"prettier.htmlWhitespaceSensitivity": "ignore",
"prettier.trailingComma": "none",
// 两者会在格式化js时冲突,需要关闭默认js格式化程序
"javascript.format.enable": false,
// 使用单引号
"javascript.preferences.quoteStyle": "single",
// 使用单引号
"typescript.preferences.quoteStyle": "single",
// 去掉非必要的逗号
"javascript.format.semicolons": "remove",
// 去掉非必要的逗号
"typescript.format.semicolons": "remove",
// 中括号左括号后边加空格和右括号前面加空格
"javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": true,
// 构造函数关键字后面加个空格
"javascript.format.insertSpaceAfterConstructor": true,
// 让函数(名)和后面的括号之间加个空格
"javascript.format.insertSpaceBeforeFunctionParenthesis": true
}
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
.eslintrc.js
配置
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/essential',
'@vue/standard'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
"eol-last": 0,
'camelcase': [0, { properties: 'always' }],
'no-extra-boolean-cast': 0,
'standard/no-callback-literal': 0
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 浏览器兼容问题
- window自带的
atob
、btoa
- 安装
js-base64
(有时候也会造成兼容性问题,不太好) - 安装
jsencrypt
(推荐使用)import JSEncrypt from 'jsencrypt'
const decrypt = new JSEncrypt()
或const encrypt = new JSEncrypt()
- 解码
decrypt.decrypt()
- 加密
encrypt.encrypt()
# Swiper5在ie不兼容问题
# 使用方法
npm i swiper -S
- mian.js中引入
import 'swiper/js/swiper.min'
import 'swiper/css/swiper.min.css'
# 原因
Swiper.js 这个 npm 包里面还使用了 dom7
和 ssr-window
,所以需要对这两个插件进行 Babel 转 ES5
# 解决方案
Vue CLI 2.x 下,在 build/webpack.base.config.js 文件中修改
// ...
modules: {
rules: [
// ...
{
test: /\.js$/,
loader: 'babel-loader',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/swiper/dist/js/'),
resolve('node_modules/webpack-dev-server/client'),
// 新增
resolve('node_modules/swiper'),
resolve('node_modules/dom7'),
resolve('node_modules/ssr-window')
]
},
// ...
]
}
// ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Vue CLI 3.x 下
在 vue.config.js
中增加 transpileDependencies
配置
module.exports = {
transpileDependencies: [
"swiper",
"dom7",
"ssr-window"
]
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 禁用浏览器缓存
对请求拦截器进行处理,对所有的GET
请求都禁用缓存
// GET请求禁用缓存/兼容ie11
if (config.method.toUpperCase() === 'GET') {
config.headers['cache-control'] = 'no-cache'
config.headers.Pragma = 'no-cache'
}
1
2
3
4
5
2
3
4
5
# 自动粘贴功能
使用navigator.clipboard.readText()
获取粘贴板的内容
注意:undefined原因是因为navigator.clipboard对象只能在安全网络环境中才能使用, 也就是,localhost中,或者https中才能正常使用,直接用ip地址访问时不可以的呢 另,剪贴板禁用提醒
const giftCardInputRef = this.$refs.giftCardInput
navigator.clipboard
.readText()
.then((text) => {
console.log('获取剪贴板成功:', text)
// AAAA-BBBB-CCCC-DDDD
const reg = /^[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}$/g
if (reg.test(text)) {
text.split('-').forEach((str, index) => (giftCardInputRef[`value${index + 1}`] = str))
giftCardInputRef.setIndex(4)
giftCardInputRef.setInputFocus('input4')
} else {
giftCardInputRef.$refs.input1.value = text
giftCardInputRef.setInputFocus('input1')
}
})
.catch((error) => {
console.log('获取剪贴板失败: ', error)
})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 校验
输入值不能小于0,小数点不能超过两位
方法一(不推荐,因为用户快速输入会超过两位,存在缺陷):
<el-input
v-model.trim="form.amount"
placeholder="请输入售后运费金额"
@keyup.native="checkInteger"
>
checkInteger (e) {
const valueInput = e.target.value
if (isNaN(valueInput)) {
e.target.value = ''
}
if (valueInput.charAt(valueInput.length - 4) === '.') {
e.target.value = valueInput.slice(0, -1)
}
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
方法二:
// 正则检验售后运费精确到小数点后两位
const reg = /^(([0-9]+\.[0-9]{1})|([0-9]+\.[0-9]{1,2})|([0-9]*[1-9][0-9]*))$/
if (!reg.test(this.form.amount)) {
this.$toast('金额最多填至小数点后2位')
return
}
1
2
3
4
5
6
2
3
4
5
6
方法三:
amount: [
{ required: true, message: '售后运费金额不能为空' },
{
validator: (rule, value, callback) => {
const mobileReg = /^(([0-9]+\.[0-9]{1})|([0-9]+\.[0-9]{1,2})|([0-9]*[1-9][0-9]*))$/
const pass = mobileReg.test(value)
if (!pass) {
callback(new Error('售后运费金额最多填至小数点后2位'))
return
}
callback()
}
}
],
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
输入值不能小于0,小数点不能超过两位,请控制在(0, 99999999.99]范围内
budgetFormRules: {
amount: [{ required: true, validator: validateTipsNum(true, 0, 99999999.99) }]
},
1
2
3
2
3
/* 验证数字 */
export const validateTipsNum = (required, min = 0, max = 999999) => (rule, value, callback) => {
if (!required && value === '') callback()
if (!validateNum(value, min, max)) {
if (max === 99999999.99) {
return callback(new Error(`请控制在(${min}, ${max}]范围内`))
} else {
return callback(new Error(`请控制在(${min}, ${max})整数范围内`))
}
}
callback()
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
/* 数字限制 */
export function validateNum(num, min = 0, max = 999999) {
// 检验合法性
const len = String(max).length
let reg
if (max === 99999999.99) {
reg = new RegExp(`^-?(([1-9]{1}\\d{0,9)|([0-9]+\.[0-9]{1,2})|([0-9]*[1-9][0-9]*))$`)
} else {
reg = new RegExp(`^-?(([1-9]{1}\\d{0,${len}})|(0{1}))$`)
}
const pass = reg.test(num)
if (!pass) return pass
const n = Number(num)
return !isNaN(n) && n >= min && n <= max
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 纯前端搜索功能
props: {
list: {
type: Array,
default () {
// eg: [{ id: 'ID', text: '文本' }]
return []
}
}
},
data () {
return {
enterpriseList: [], // 用户通过搜索所能见到的企业
searchInfo: '' // 搜索框内容
}
},
methods: {
// 搜索
toSearch () {
this.enterpriseList = this.list.filter(item => {
return item.text.includes(this.searchInfo.trim())
})
},
// 清空搜索框和筛选框
clearAndRefresh () {
this.searchInfo = ''
this.enterpriseList = this.list
}
}
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
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
编辑 (opens new window)
上次更新: 2022/09/30, 14:37:58