开箱即用的 Vue3 + Vant4 移动端模板
github
gitee
在线预览
## 项目搭建
- 参考vite官网:https://vitejs.cn
pnpm create vite
## 代码规范
### 集成 editorconfig 配置
- EditorConfig 有助于为不同 IDE 编辑器上处理同一项目的多个开发人员维护一致的编码风格。
```yaml
# http://editorconfig.org
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off
trim_trailing_whitespace = false
pnpm i eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin vue-global-api -D
module.exports = {
root: true,
env: {
browser: true,
node: true
},
globals: {
Message: true,
env: true,
useRoute: true,
useRouter: true,
useStore: true
},
/* 指定如何解析语法。可以为空,但若不为空,只能配该值,原因见下文。*/
parser: 'vue-eslint-parser',
/* 优先级低于parse的语法解析配置 */
parserOptions: {
parser: '@typescript-eslint/parser', // Specifies the ESLint parser
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
sourceType: 'module', // Allows for the use of imports
ecmaFeatures: {
jsx: true
}
},
extends: [
'vue-global-api',
'eslint:recommended',
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'plugin:prettier/recommended'
],
plugins: ['vue'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 1 : 0,
'no-debugger': process.env.NODE_ENV === 'production' ? 1 : 0,
'no-useless-concat': 1, // 禁止不必要的字符串字面量或模板字面量的连接
'no-useless-escape': 0, // 禁止不必要的转义字符
'consistent-return': 0, // 要求 return 语句要么总是指定返回的值,要么不指定
'camelcase': 0, // 强制使用骆驼拼写法命名约定
'no-redeclare': 1, // 禁止多次声明同一变量
'array-callback-return': 1, // 强制数组方法的回调函数中有 return 语句,Array有几种过滤,映射和折叠的方法。如果我们忘记return在这些回调中写入语句,那可能是一个错误。
'default-case': 1, // 要求 switch 语句中有 default 分支
'no-fallthrough': 1, // 禁止 case 语句落空
'no-lonely-if': 1, // 禁止 if 作为唯一的语句出现在 else 语句中.如果一个if陈述是该else块中唯一的陈述,那么使用一个else if表格通常会更清晰。
'no-irregular-whitespace': 1, // 禁止在字符串和注释之外不规则的空白
'prefer-const': 0, // 要求使用 const 声明那些声明后不再被修改的变量.如果一个变量从不重新分配,使用const声明更好。const 声明告诉读者,“这个变量永远不会被重新分配,”减少认知负荷并提高可维护性。
'no-use-before-define': 1, // 禁止在变量定义之前使用它们
'vue/attributes-order': 2, // vue api使用顺序
'vue/no-multiple-template-root': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/no-var-requires': 0,
'@typescript-eslint/no-unused-vars': 0,
'@typescript-eslint/ban-ts-comment': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-empty-function': 0,
'vue/multi-word-component-names': 0
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)'],
env: {
mocha: true
}
}
]
}
module.exports = {
printWidth: 100, // 单行输出(不折行)的(最大)长度
tabWidth: 2, // 每个缩进级别的空格数
tabs: false, // 使用制表符 (tab) 缩进行而不是空格 (space)。
semi: false, // 是否在语句末尾打印分号
singleQuote: true, // 是否使用单引号
quoteProps: "as-needed", // 仅在需要时在对象属性周围添加引号
jsxSingleQuote: false, // jsx 不使用单引号,而使用双引号
trailingComma: "none", // 去除对象最末尾元素跟随的逗号
bracketSpacing: true, // 是否在对象属性添加空格
jsxBracketSameLine: true, // 将 > 多行 JSX 元素放在最后一行的末尾,而不是单独放在下一行(不适用于自闭元素),默认false,这里选择>不另起一行
arrowParens: "always", // 箭头函数,只有一个参数的时候,也需要括号
proseWrap: "always", // 当超出print width(上面有这个参数)时就折行
htmlWhitespaceSensitivity: "ignore", // 指定 HTML 文件的全局空白区域敏感度, "ignore" - 空格被认为是不敏感的
vueIndentScriptAndStyle: false, // 在VUE文件中不要缩进脚本和样式标记
stylelintIntegration: true,
endOfLine: "auto"
}
# windows下需要先执行 npx husky install
npx mrm@2 lint-staged
{
"scripts": {
"lint": "eslint ./src/**/*{.js,.jsx,.ts,.tsx,.vue} --fix", // 这条除外
"prepare": "husky install"
},
"devDependencies": {
"husky": "^7.0.4",
"lint-staged": "^12.4.1",
},
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": "npm run lint"
}
}
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# npx lint-staged
npm run lint
安装依赖
pnpm install vue-router@4
src 目录创建 router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import Login from '/@/views/login.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/login',
component: Login
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
在 main.ts 中注册路由
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'
const app = createApp(App)
app.use(router).mount('#app')
App.vue 中使用路由占位符
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
keep-alive>
router-view>
pnpm install pinia
src 目录创建 store/index.ts
import { App } from 'vue'
import { createPinia } from 'pinia'
export const setupStore = (app: App) => {
app.use(createPinia())
}
在 main.ts 中注册
import { setupStore } from './store'
setupStore(app)