Vue 3 + Typescript + Vite2.0 搭建移动端 代码规范以及注意的点

vue

<!--

* @Descripttion: Vue 3 + Typescript + Vite2.0 项目简介

-->

# Vue 3 + Typescript + Vite + vant3 搭建移动端通用架子

pc 管理系统请参考移步:VUE VBEN ADMIN2.0 (vite2.0+vue3+ts+antd-design-vue)

github 地址:git clone https://github.com/anncwb/vue-vben-admin.git vue-vben-admin-2.0

项目文档:https://vvbin.cn/doc-next/

element-plus(支持 vue3) 文档:https://element-plus.gitee.io/#/zh-CN/component/installation

vite2.0 中文文档:https://cn.vitejs.dev/

vue3 官方文档:https://v3.cn.vuejs.org/api/

Typescript 官方文档:https://www.tslang.cn/docs/home.html

vant3 官方文档:https://vant-contrib.gitee.io/vant/v3/#/zh-CN/home

vue-i18n@next 国际化配置文档:https://vue-i18n.intlify.dev/introduction.html

### 初始化项目 [yarn 和 npm 的区别不赘述]

npm init @vitejs/app or yarn create @vitejs/app ---> 输入项目名称 ---> 选择 vue-ts [vue3+TS]

### 安装依赖

npm i or cnpm i

### 启动项目

cnpm run dev

### 安装相关依赖 yarn 或者 cnpm npm 命令都行

yarn add xxx

npm i vue-i18n@next -S or cnpm i vue-i18n@next -S

npm i vue-router@4 -S or cnpm i vue-router@4 -S

npm i vuex@next -S or cnpm i vuex@next -S

### 注意问题

node api 报错 比如配置文件使用 require

node.js 不是内置对象的一部分,如果想用 typescript 写 Node.js,则需要引入第三方声明文件

解决办法:npm i @types/node -D or cnpm i @types/node -D

tsconfig.json types 中配置 node 字段

### 代码规范

vscode 提示无法在只读编辑器中编辑 json 文件

File → Preferences → Settings --> Eslint

Eslint 官方文档:https://eslint.org/docs/rules/

prettier 官方文档:https://prettier.io/docs/en/configuration.html

eslint-plugin-vue 官方文档:https://eslint.vuejs.org/user-guide/#usage 自动修复 eslint 报错

npm i eslint-plugin-vue -D or cnpm i eslint-plugin-vue -D

vscode Vetur 插件 ---> vue 高亮插件

vscode ESlint 插件 ---> Eslint 插件用于根据工程目录的.eslintrc.js 配置文件在编辑器中显示一些错误提示,后面的自定格式化根据这里的错误提示进行格式化操作

如果是 vue-cli 创建的项目 创建的时候把 Linter/Formatter 选上(默认已选上) 下一步选择 Eslint+Prettier --> Lint on save

// eslint 配置项,保存时自动修复

"editor.codeActionsOnSave": {

"source.fixAll.eslint": true

},

// 默认使用 prettier 格式化支持的文件

"editor.defaultFormatter": "esbenp.prettier-vscode",

// 自动设定 eslint 工作区

"eslint.workingDirectories": [

{ "mode": "auto" }

],

"explorer.confirmDelete": false,

"diffEditor.ignoreTrimWhitespace": true,

"eslint.codeAction.showDocumentation": {

"enable": true

},

"editor.codeActionsOnSave": {

"source.fixAll.eslint": true

},

"eslint.format.enable": true,

"eslint.validate": ["javascript", "vue", "html","jsx", "javascriptreact"],

"editor.suggest.snippetsPreventQuickSuggestions": false,

"files.associations": {

"\*.vue": "html"

},

"editor.formatOnSave": true

//由于 prettier 不能格式化 vue 文件 template 所以使用 js-beautify-html 格式化

"vetur.format.defaultFormatter.html": "js-beautify-html",

"vetur.format.defaultFormatterOptions": {

"js-beautify-html": {

"wrap*attributes": "force-aligned" //属性强制折行对齐

}

},

"prettier.singleQuote": true, //使用单引号而不是双引号

"prettier.jsxBracketSameLine": true, //将>多行 JSX 元素放在最后一行的末尾,而不是单独放在下一行

"prettier.printWidth": 120, // 超过最大值换行

"prettier.tabWidth": 2, // 缩进字节数

"prettier.useTabs": true, // 缩进使用 tab

"prettier.semi": false, // 句尾添加分号

"prettier.singleQuote": true, // 使用单引号代替双引号

"prettier.proseWrap": "preserve", // 默认值。因为使用了一些折行敏感型的渲染器(如 GitHub comment)而按照 markdown 文本样式进行折行

"prettier.arrowParens": "avoid", // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号

"prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"

"prettier.endOfLine": "auto", // 结尾是 \n \r \n\r auto

"prettier.htmlWhitespaceSensitivity": "ignore",

"prettier.ignorePath": ".prettierignore", // 不使用 prettier 格式化的文件填写在项目的.prettierignore 文件中

"prettier.requireConfig": false, // Require a "prettierconfig" to format prettier

"prettier.trailingComma": "none", // 在对象或数组最后一个元素后面是否加逗号

/* 每种语言默认的格式化规则 \_/

"[html]": {

"editor.defaultFormatter": "esbenp.prettier-vscode"

},

"[css]": {

"editor.defaultFormatter": "esbenp.prettier-vscode"

},

"[scss]": {

"editor.defaultFormatter": "esbenp.prettier-vscode"

},

"[javascript]": {

"editor.defaultFormatter": "esbenp.prettier-vscode"

},

"[vue]": {

"editor.defaultFormatter": "esbenp.prettier-vscode"

},

"[json]": {

"editor.defaultFormatter": "esbenp.prettier-vscode"

},

安装插件让 ESLint 支持 TypeScript

npm i typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin -D

当我们执行 npm run format 时还会报各种奇怪的错误 如:error: Delete ⏎ (prettier/prettier) at src/pages/xxx 等;这是因为 prettier 配置和 vscode 编辑器 prettier 配置冲突导致的 在 rules 中配置下覆盖掉就可以了

出现了下面的警告:} expected css(css lcurlyexpected), 解决方案:settings.json 中配置如下

"files.associations": {

"_.vue": "vue",

"_.tpl": "html"

},

### git 提交代码钩子校验

npm i husky lint-staged -D

or

cnpm i husky lint-staged -D

## package.json 中配置 GitHub 文档:https://github.com/typicode/husky

"husky": {

"hooks": {

"pre-commit": "lint-staged",

"pre-push": "lint-staged"

}

},

"lint-staged": {

"\*.{js,jsx,md,html,css}": [

"prettier --write",

"git add"

]

}

### vm vw 布局适配方案 以及 css 预处理器 {这边先选择 less} UI 选型 {自己封装常用的 or 选择一种功能比较齐全的移动端 UI 库}

cnpm i postcss-viewport-units postcss-px-to-viewport postcss-write-svg autoprefixer -D

cnpm i less -D

cnpm i vant@next -S

cnpm i vite-plugin-imp -D // 按需加载 GitHub 文档:https://github.com/onebay/vite-plugin-imp

vant 官方网站:https://vant-contrib.gitee.io/vant/v3/#/zh-CN

其实在 Vite 中无须考虑按需引入的问题。Vite 在构建代码时,会自动通过 Tree Shaking 移除未使用的 ESM 模块。而 Vant 3.0 内部所有模块都是基于 ESM 编写的,天然具备按需引入的能力。现阶段遗留的问题是,未使用的组件样式无法被 Tree Shaking 识别并移除,后续 vant 团队会考虑通过 Vite 插件的方式进行支持

### 环境变量和打包命令配置

根目录下新建文件

.env.development (开发)

.env.test (测试)

.env.production (生产)

package.json 中配置打包命令

"build:dev": "vue-tsc --noEmit && vite build --mode development",

"build:test": "vue-tsc --noEmit && vite build --mode test",

"build:prod": "vue-tsc --noEmit && vite build --mode production"

打包命令

cnpm run build:dev // 本地包

cnpm run build:test // 测试包

cnpm run build:prod // 生产包

### 使用 http-server 开启一个本地服务器 预览效果

npm install http-server -g

cd dist

http-server -c-1(只输入 http-server 的话,更新了代码后,页面不会同步更新)ctrl + c 即可关闭

### 调试工具

cnpm i vconsole -S

在 main.ts 引入

import Vconsole from 'vconsole';

new Vconsole();

### PWA

参考文档:https://github.com/antfu/vite-plugin-pwa

cnpm i vite-plugin-pwa -D

配置 vite.config.ts 文件

import { VitePWA } from 'vite-plugin-pwa'

plugins:[

VitePWA({

manifest: {},

workbox: {

skipWaiting: true,

clientsClaim: true

}

})

]

### 组件样式按需加载配置

参考文档:https://github.com/anncwb/vite-plugin-style-import

配置 vite.config.ts 文件

cnpm i vite-plugin-style-import -D

import styleImport from 'vite-plugin-style-import'

css:{

preprocessorOptions:{

less:{

modifyVars:{},

javascriptEnabled: true

}

}

},

plugins:[

styleImport({

libs:[

{

libraryName: 'ant-design-vue',

esModule: true,

resolveStyle: name => `ant-design-vue/es/${name}/style/index`

}

]

})

]

### 生产环境生成 .gz 文件.

[content-encoding:gzip]

压缩代码,在传输的时候用 gzip 压缩,提高资源访问速度。后端以 nginx 为例的话,在 nginx.conf 需要开启 gizp 服务:

gzip on; //开启 gzip 压缩功能

这样你就可以在 network 查看到 content-encoding:gzip 这个选项

参考文档:https://github.com/anncwb/vite-plugin-compression

cnpm i vite-plugin-compression -D

配置 vite.config.ts 文件

import viteCompression from 'vite-plugin-compression'

plugins:[

viteCompression({

verbose: true,

disable: false,

threshold: 10240,

algorithm: 'gzip',

ext: '.gz'

})

]

### 国际化配置

安装 js-cookie

cnpm i js-cookie -S

cnpm i @types/js-cookie -D

参考文档:https://www.npmjs.com/package/js-cookie

cnpm i vue-i18n@next -S

### http 请求库

cnpm i axios -S

### normalize.css 更好的 reset.css 方案

cnpm i normalize.css -S

参考文档:https://github.com/necolas/normalize.css

项目环境以及打包命令配置

项目根目录下创建 .env.test  【测试环境】 .env.development  【开发环境】  .env.production 【生产环境】

分别对应内容

NODE_ENV=test

VITE_APP_BASE_URL='https://www.test.com/'

NODE_ENV=development

VITE_APP_BASE_URL='api'

NODE_ENV=production

VITE_APP_BASE_URL='https://www.prod.com/'

文件里获取  console.log(import.meta.env.VITE_APP_BASE_URL, '环境变量')

package.json文件下面配置

    "build:dev": "vue-tsc --noEmit && vite build --mode development",

"build:test": "vue-tsc --noEmit && vite build --mode test",

"build:prod": "vue-tsc --noEmit && vite build --mode production"

关于代码规范:都可以自定义规则以下是自己简单的配置规则(提供参考具体查看对应官方文档配置属性)

.eslintignore文件

*.sh

node_modules

*.md

*.woff

*.ttf

.vscode

.idea

dist

/public

/docs

.husky

.local

/bin

Dockerfile

.eslintrc.js文件

/*

* @Descripttion: eslint代码规范

*/

module.exports = {

parser: 'vue-eslint-parser',

parserOptions: {

parser: '@typescript-eslint/parser',

ecmaVersion: 2020,

sourceType: 'module',

ecmaFeatures: {

jsx: true

}

},

extends: [

'plugin:vue/vue3-recommended',

'plugin:@typescript-eslint/recommended',

'prettier/@typescript-eslint',

'plugin:prettier/recommended'

],

rules: {

'@typescript-eslint/ban-ts-ignore': 'off',

'@typescript-eslint/explicit-function-return-type': 'off',

'@typescript-eslint/no-explicit-any': 'off',

'@typescript-eslint/no-var-requires': 'off',

'@typescript-eslint/no-empty-function': 'off',

'vue/custom-event-name-casing': 'off',

'no-use-before-define': 'off',

// 'no-use-before-define': [

// 'error',

// {

// functions: false,

// classes: true,

// },

// ],

'@typescript-eslint/no-use-before-define': 'off',

// '@typescript-eslint/no-use-before-define': [

// 'error',

// {

// functions: false,

// classes: true,

// },

// ],

'@typescript-eslint/ban-ts-comment': 'off',

'@typescript-eslint/ban-types': 'off',

'@typescript-eslint/no-non-null-assertion': 'off',

'@typescript-eslint/explicit-module-boundary-types': 'off',

'@typescript-eslint/no-unused-vars': [

'error',

{

argsIgnorePattern: '^h$',

varsIgnorePattern: '^h$'

}

],

'no-unused-vars': [

'error',

{

argsIgnorePattern: '^h$',

varsIgnorePattern: '^h$'

}

],

'space-before-function-paren': 'off',

quotes: ['error', 'single'],

'comma-dangle': ['error', 'never'],

"no-console": process.env.NODE_ENV === "production" ? "error" : "off",

"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"

}

}

.prettierignore文件

/dist/*

.local

.output.js

/node_modules/**

**/*.svg

**/*.sh

/public/*

.prettierrc.js文件

/*

* @Descripttion: prettier.config.js or .prettierrc.js package.json 中配置prettier属性

*/

// 如果vscode配置中有的这边可以不用再配置

module.exports = {

useTabs: false,

vueIndentScriptAndStyle: true,

quoteProps: 'as-needed',

jsxSingleQuote: false,

arrowParens: 'always',

htmlWhitespaceSensitivity: 'strict',

endOfLine: 'lf',

printWidth: 200, // 换行字符串阈值

tabWidth: 2, // 设置工具每一个水平缩进的空格数

singleQuote: true, // 用单引号

semi: false, // 句末是否加分号

trailingComma: 'none', // 最后一个对象元素加逗号

bracketSpacing: true, // 对象,数组加空格

jsxBracketSameLine: false, // jsx > 是否另起一行

disableLanguages: ["vue"] // 不格式化vue文件,vue文件的格式化单独设置

}

postcss.config.js文件

/*

* @Descripttion: postcss.config.js

*/

module.exports = {

plugins: {

autoprefixer: {

/* PostCSS plugin to parse CSS and add vendor prefixes to CSS rules */

/* 配置文档链接:https://github.com/postcss/autoprefixer#options */

overrideBrowserslist: [

'last 2 versions' // 最后两个版本

]

},

'postcss-viewport-units': {

/* vw兼容方案 */

/* 配置文档链接:https://github.com/springuper/postcss-viewport-units#options */

},

'postcss-px-to-viewport': {

/* 将px单位转换为视口单位的 (vw, vh, vmin, vmax) */

/* 配置文档链接:https://github.com/evrone/postcss-px-to-viewport/blob/master/README_CN.md#%E9%85%8D%E7%BD%AE%E5%8F%82%E6%95%B0 */

viewportWidth: 375,

viewportUnit: 'vw',

unitPrecision: 3,

minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位,你也可以设置为你想要的值

mediaQuery: false,

// selectorBlackList: ['.vant'], // 以xxx开头

include: [], // 包括

exclude: [] // 排除

},

'postcss-write-svg': {

/* 在retina屏绘制1px细线 */

/* 配置文档链接:https://github.com/jonathantneal/postcss-write-svg#options */

},

}

}

tsconfig.json文件

{

"compilerOptions": {

"target": "esnext",

"module": "esnext",

"moduleResolution": "node",

"strict": true,

"jsx": "preserve",

"sourceMap": true,

"resolveJsonModule": true,

"esModuleInterop": true,

"lib": ["esnext", "dom", "ES2015.promise"],

"types": ["vite/client", "node"],

"typeRoots": ["./node_modules/@types/", "./src/types"],

"paths": {

"@": ["./src"]

}

},

"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],

"exclude": ["node_modules"]

}

vite.config.ts配置

/*

* @Descripttion: vite.config.ts vite2.0

*/

import { defineConfig } from 'vite'

import vue from '@vitejs/plugin-vue'

import viteCompression from 'vite-plugin-compression'

const path = require('path')

const resolve = (dir: string) => path.join(__dirname, dir)

// https://vitejs.dev/config/

export default defineConfig({

base: process.env.NODE_ENV === 'production' ? './' : '/',

plugins: [

vue(),

// 默认情况下,小于1501字节的文件不会被压缩

viteCompression({

// 是否在控制台输出压缩结果

verbose: true,

// 是否禁用

disable: false,

// 体积大于 threshold 才会被压缩,单位 b

threshold: 10240,

// 压缩算法

algorithm: 'gzip',

// 生成的压缩包后缀

ext: '.gz',

// 压缩后是否删除源文件

deleteOriginFile: false

})

],

// 别名

resolve: {

alias: {

'@': resolve('src'),

// 解决vue-i18n警告You are running the esm-bundler build of vue-i18n.

'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'

}

},

// 代理解决dev模式跨域

server: {

host: '0.0.0.0',

// https: false,

port: 9999, //启动端口

open: true, // 是否自动打开浏览器

cors: true,

proxy: {

// 如果是 /api 打头,则访问地址如下

'/api': {

target: 'http://jsonplaceholder.typicode.com',

changeOrigin: true,

// ws: true,

rewrite: (path) => path.replace(/^\/api/, '')

}

}

},

css: {

preprocessorOptions: {

less: {

modifyVars: {

// Used for global import to avoid the need to import each style file separately

// reference: Avoid repeated references

hack: `true; @import (reference) "${resolve('src/assets/style/index.less')}";`

},

javascriptEnabled: true

}

}

},

build: {

target: 'es2015',

outDir: 'dist',

// 生产环境移除 console

terserOptions: {

compress: {

drop_console: process.env.NODE_ENV === 'production' ? true : false,

drop_debugger: process.env.NODE_ENV === 'production' ? true : false

}

}

}

})

vscode  setting json配置:

{

"workbench.colorTheme": "Atom One Dark",

"workbench.iconTheme": "vscode-icons",

"git.ignoreWindowsGit27Warning": true,

"[html]": {

"editor.defaultFormatter": "HookyQR.beautify"

},

"[javascript]": {

"editor.defaultFormatter": "HookyQR.beautify"

},

"[json]": {

"editor.defaultFormatter": "vscode.json-language-features"

},

"fileheader.customMade": {

"Descripttion": "",

"version": "",

"Author": "lhl",

"Date": "Do not edit",

"LastEditors": "lhl",

"LastEditTime": "Do not Edit"

},

"fileheader.cursorMode": {

"name": "",

"test": "test font",

"msg": "",

"param": "",

"return": ""

},

"explorer.confirmDelete": false,

"diffEditor.ignoreTrimWhitespace": true,

"eslint.codeAction.showDocumentation": {

"enable": true

},

"editor.codeActionsOnSave": {

"source.fixAll.eslint": true

},

"eslint.workingDirectories": [{ "mode": "auto" }],

"editor.defaultFormatter": "esbenp.prettier-vscode",

"eslint.format.enable": true,

"eslint.validate": ["javascript", "vue", "html", "typescript"],

"editor.suggest.snippetsPreventQuickSuggestions": false,

"files.associations": {

"*.vue": "vue",

"*.tpl": "html"

},

"vetur.format.defaultFormatter.html": "js-beautify-html",

"vetur.format.defaultFormatterOptions": {

"js-beautify-html": {

"wrap_attributes": "force-aligned"

}

},

"prettier.singleQuote": true,

"prettier.printWidth": 200,

"prettier.tabWidth": 2,

"prettier.useTabs": true,

"prettier.semi": false,

"prettier.proseWrap": "preserve",

"prettier.arrowParens": "avoid",

"prettier.bracketSpacing": true,

"prettier.endOfLine": "auto",

"prettier.htmlWhitespaceSensitivity": "ignore",

"prettier.ignorePath": ".prettierignore",

"prettier.requireConfig": false,

"prettier.trailingComma": "none",

"editor.formatOnSave": false,

"[dart]": {

"editor.formatOnSave": true,

"editor.formatOnType": true,

"editor.rulers": [

80

],

"editor.selectionHighlight": false,

"editor.suggest.snippetsPreventQuickSuggestions": false,

"editor.suggestSelection": "first",

"editor.tabCompletion": "onlySnippets",

"editor.wordBasedSuggestions": false

}

}

package.json文件

{

"name": "vite-project",

"version": "0.0.0",

"scripts": {

"dev": "vite",

"build": "vue-tsc --noEmit && vite build",

"serve": "vite preview",

"build:dev": "vue-tsc --noEmit && vite build --mode development",

"build:test": "vue-tsc --noEmit && vite build --mode test",

"build:prod": "vue-tsc --noEmit && vite build --mode production"

},

"dependencies": {

"@types/js-cookie": "^2.2.6",

"@vant/area-data": "^1.0.0",

"axios": "^0.21.1",

"js-cookie": "^2.2.1",

"normalize.css": "^8.0.1",

"vant": "^3.0.12",

"vconsole": "^3.4.0",

"vue": "^3.0.5",

"vue-i18n": "^9.0.0",

"vue-router": "^4.0.5",

"vuex": "^4.0.0"

},

"devDependencies": {

"@types/js-cookie": "^2.2.6",

"@types/node": "^14.14.37",

"@typescript-eslint/eslint-plugin": "^4.20.0",

"@typescript-eslint/parser": "^4.20.0",

"@vitejs/plugin-vue": "^1.2.1",

"@vue/compiler-sfc": "^3.0.5",

"autoprefixer": "^10.2.5",

"eslint": "^7.23.0",

"eslint-config-prettier": "^8.1.0",

"eslint-plugin-prettier": "^3.3.1",

"eslint-plugin-vue": "^7.8.0",

"husky": "^6.0.0",

"less": "^4.1.1",

"lint-staged": "^10.5.4",

"postcss-px-to-viewport": "^1.1.1",

"postcss-viewport-units": "^0.1.6",

"postcss-write-svg": "^3.0.1",

"prettier": "^2.2.1",

"typescript": "^4.1.3",

"vite": "^2.1.5",

"vite-plugin-compression": "^0.2.4",

"vite-plugin-imp": "^2.0.5",

"vue-tsc": "^0.0.15"

},

"husky": {

"hooks": {

"pre-commit": "lint-staged",

"pre-push": "lint-staged"

}

},

"lint-staged": {

"*.{js,jsx,md,html,css}": [

"prettier --write",

"git add"

]

}

}

以上代码纯属自己整理和测试,未经允许请勿随意转载,若有不正请及时告知!!

EditorConfig for Visual Studio Code (有喜爱的可以配置上这个下载vscode插件即可配置)

根目录下创建  .editorconfig文件 

配置参考:https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig

以上是 Vue 3 + Typescript + Vite2.0 搭建移动端 代码规范以及注意的点 的全部内容, 来源链接: utcz.com/z/378594.html

回到顶部