Vite + Vue3 <script setup> + TS + Pinia + Element-Plus 项目搭建
![也不是很圆](https://picx.zhimg.com/v2-95403e3fb6cc1e189f052505d2101cfb_l.jpg?source=172ae18b)
![](https://pic1.zhimg.com/v2-4812630bc27d642f7cafcd6cdeca3d7a.jpg?source=88ceefae)
使用 Vite 创建项目
使用我最喜爱的
pnpm
pnpx create-vite
pnpm create vite
如果和我一样嫌弃
pnpm
pnpx
太长,可以设置 alias
// .zshrc
alias p=pnpm
alias px=pnpx
这样就清爽多了
px create-vite
当然选择我最喜爱的
Vue
Select a framework:
vanilla
❯ vue
react
preact
svelte
Vue3
<script setup>
语法糖对
TS
的支持棒棒的,特别是
props
Select a variant:
❯ vue-ts
进入项目,安装依赖
p i
完成
VS Code 不要安装
Vuter
插件,如果安装了就卸载,用
Volar
配置 ESLint
生成配置文件
用
eslint
命令生成配置文件
px eslint --init
How would you like to use ESLint?
To check syntax only
To check syntax and find problems
❯ To check syntax, find problems, and enforce code style
What type of modules does your project use?
❯ JavaScript modules (import/export)
CommonJS (require/exports)
None of these
Which framework does your project use?
React
❯ Vue.js
None of these
Does your project use TypeScript? (y/N) Y
Where does your code run? (Press <space> to select, <a> to
toggle all, <i> to invert selection)
❯◉ Browser
◯ Node
How would you like to define a style for your project? (Us
e arrow keys)
❯ Use a popular style guide
Answer questions about your style
Inspect your JavaScript file(s)
Which style guide do you want to follow?
❯ Airbnb: https://github.com/airbnb/javascript
Standard: https://github.com/standard/standard
Google: https://github.com/google/eslint-config-google
什么格式都行
What format do you want your config file to be in? (Use ar
row keys)
❯ JavaScript
JSON
最后是否使用
npm
安装依赖,我不用
npm
并且我的项目是
Monorepo
,所以我自己安装依赖
The config that you've selected requires the following dependencies:
eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest eslint-config-airbnb-base@latest eslint@^7.32.0 || ^8.2.0 eslint-plugin-import@^2.25.2 @typescript-eslint/parser@latest
? Would you like to install them now with npm? (Y/n) n
注意如果依赖的语义版本号使用的
||
两边有空格,就需要用引号包起来
p add -D eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest eslint-config-airbnb-base@latest "eslint@^7.32.0 || ^8.2.0" eslint-plugin-import@^2.25.2 @typescript-eslint/parser@latest
.eslintrc.js
创建完成
.eslintrc.js 配置
使用 Vue3 规则
// .eslintrc.js
module.exports = {
extends: [
'plugin:vue/vue3-recommended',
};
允许
vite.config.ts
使用
devDependencies
中的依赖
// .eslintrc.js
module.exports = {
rules: {
'import/no-extraneous-dependencies': [
'error',
devDependencies: ['vite.config.ts'],
};
Missing file extension
// .eslintrc.js
module.exports = {
rules: {
'import/extensions': [
'error',
'ignorePackages',
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
}
枚举 is already declared in the upper scope
// .eslintrc.js
module.exports = {
rules: {
'no-shadow': 'off',
'@typescript-eslint/no-shadow': ['off'],
}
枚举成员 is defined but never used
// .eslintrc.js
module.exports = {
rules: {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error',
}
用 ESLint 代替 Prettier
ESLint 也是可以作为格式化工具,不需要用 Prettier
安装 ESLint 插件,启用 ESLint 的 Format 功能,启用保存时格式化代码
添加 lint script
// package.json
"scripts": {
"lint": "eslint --ext .ts,.tsx,.vue .",
"lint:fix": "eslint --ext .ts,.tsx,.vue --fix .",
}
配置别名 @
配置的别名要让 Vite 、TS、ESLint 都认识才行
Vite 配置别名
安装
@types/node
p add @types/node -D
// vite.config.ts
import path from 'path';
export default defineConfig({
resolve: {
alias: [
{ find: /^@\//, replacement: `${path.resolve(__dirname, './src')}/` },
});
// tsconfig.node.json
"compilerOptions": {
"allowSyntheticDefaultImports": true
}
TS 配置别名
// tsconfig.json
"compilerOptions": {
"baseUrl": ".",
"paths": {"@/*": ["src/*"]},
}
ESLint 配置别名
p add -D eslint-import-resolver-alias
// .eslintrc.js
module.exports = {
settings: {
'import/resolver': {
alias: {
map: [['@', './src/']],
extensions: ['.ts', '.tsx'],
};
配置接口代理
前后端分离必备,解决跨域问题
// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/api/indicator-factory/': {
target: 'http://index-factory-yf-api.jd.com',
ws: true,
changeOrigin: true,
rewrite: (p) => p.replace(/^\/api\/indicator-factory\//, '/api/'),
});
配置 git 提交规范
px husky-init
会在项目根目录生成
.husky
目录,
husky
添加到了开发依赖,添加了
prepare
脚本
// package.json
"scripts": {
"prepare": "husky install"
"devDependencies": {
"husky": "^7.0.0"
}
每次安装依赖都会执行
prepare
提交代码前执行代码检测和测试
默认有
pre-commit
钩子,在
git commit
提交前做一些事情,比如执行代码规范检测、执行测试
// pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm lint
pnpm test
约定式提交
p add -D @commitlint/cli @commitlint/config-conventional
在项目根目录创建
commitlint.config.js
文件
// commitlint.config.js
module.exports = {
extends: [
'@commitlint/config-conventional'
}
创建
commit-msg
钩子
px husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
配置 Element Plus
p add element-plus
按需自动导入
p add -D unplugin-vue-components unplugin-auto-import
// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
export default defineConfig({
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
Components({
resolvers: [ElementPlusResolver()],
});
就可以使用了
<template>
<el-button type="primary">
Primary
</el-button>
</template>
给组件添加语法提示
// tsconfig.json
"compilerOptions": {
"types": [
"element-plus/global"
}
ESLint 忽略自动生成的
components.d.ts
和
auto-imports.d.ts
// .eslintrc.js
module.exports = {
ignorePatterns: ['components.d.ts', 'auto-imports.d.ts'],
};
自定义主题
p add -D sass
自定义主题文件
// src/styles/index.scss
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
$colors: (
'primary': (
'base': #00b575,
);
// vite.config.ts
export default defineConfig({
plugins: [
Components({
resolvers: [
ElementPlusResolver({
importStyle: 'sass',
resolve: {
alias: [
{ find: /~\//, replacement: `${path.resolve(__dirname, 'src')}/` },
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "~/styles/index.scss" as *;',
});
国际化 & Pinia全局状态管理
p add vue-i18n pinia
// i18n/LOCALE.ts
export enum LOCALE {
EN_US = 'en_US',
ZH_CN = 'zh_CN',
// i18n/index.ts
import { createI18n } from 'vue-i18n';
import { LOCALE } from './LOCALE';
export default createI18n({
locale: LOCALE.ZH_CN,
messages: {
[LOCALE.ZH_CN]: {
hello: '你好世界',
[LOCALE.EN_US]: {
hello: 'hello world',
});
// stores/app.store.ts
import { defineStore } from 'pinia';
import { computed, ref, watchEffect } from 'vue';
import zh from 'element-plus/lib/locale/lang/zh-cn';
import en from 'element-plus/lib/locale/lang/en';
import i18n from '@/i18n';
import { LOCALE } from '@/i18n/LOCALE';
export const useAppStore = defineStore('app', () => {
// 默认语言
const locale = ref(LOCALE.ZH_CN);
// element plus 语言
const elementLocale = computed(() => (locale.value === LOCALE.EN_US ? en : zh));
watchEffect(() => {
i18n.global.locale = locale.value;
// 更新语言
const updateLocale = (lang: LOCALE) => {
locale.value = lang;
return {
locale,
elementLocale,
updateLocale,
});
// main.ts
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import i18n from './i18n';
const app = createApp(App);
app.use(i18n);
app.use(createPinia());
app.mount('#app');
使用
<script setup lang="ts">
import { useAppStore } from '@/stores/app.store';
import { LOCALE } from '@/i18n/LOCALE';
const appStore = useAppStore();
</script>
<template>
<el-config-provider :locale="appStore.elementLocale">
<el-button
type="primary"
@click="appStore.updateLocale(appStore.locale === LOCALE.EN_US ? LOCALE.ZH_CN : LOCALE.EN_US)"