項目初始化
yarn create @vitejs/app my-vue-ts-app --template vue-ts
複製代碼
ts配置項
tsconfig.json
- 目前暫時採用項目構建後的默認配置
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"lib": ["esnext", "dom"],
"types": ["vite/client"],
"plugins": [{ "name": "@vuedx/typescript-plugin-vue" }]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules", "dist"]
}
複製代碼
shim.d.ts配置
declare module '*.vue' {
import { Component } from 'vue'
const mod: Component
export default mod
}
複製代碼
eslint集成配置
.eslintrc.js
yarn add -D eslint eslint-plugin-vue babel-eslint
- 根據我的習慣配置就好~
- === 總感受對
ts
的支持不是很好,待完善 ===
module.exports = {
root: true,
env: {
node: true,
},
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'plugin:prettier/recommended',
],
parserOptions: {
parser: 'babel-eslint',
},
plugins: ['prettier'],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-unused-vars': process.env.NODE_ENV === 'production' ? 'error' : 'warn',
},
}
複製代碼
prettier集成配置
.prettierrc
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier
- 根據我的習慣配置就好~
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"arrowParens": "always",
"trailingComma": "es5",
"printWidth": 90,
"useTabs": false
}
複製代碼
集成vue-router
import {RouteRecordRaw, createRouter, createWebHashHistory} from 'vue-router'
const routes:RouteRecordRaw[] = [
{ path: '/', name: 'Home', component: () => import('../views/home/home.vue') }
]
const router = createRouter({
history: createWebHashHistory(),
routes,
})
export default router
import router from './router'
createApp(App).use(router)
複製代碼
集成vuex
import { createStore, createLogger } from 'vuex'
const debug: boolean = import.meta.env.MODE === 'development'
const plugins = debug ? [createLogger({ collapsed: true })] : []
export default createStore({
state: {},
mutations: {},
actions: {},
modules: {},
strict: debug,
plugins: plugins,
})
import store from './store'
createApp(App).use(store)
複製代碼
引入less
yarn add less less-loader
- 暫無特殊配置
引入UI組件庫
- 我的使用
element-plus
,也能夠選擇使用 ant-design vue
vue add element-plus
- 自動生成相應
plugins/element.js
配置及 scss
樣式文件
- 須要在
vite.config.ts
中添加語言配置項
- 使用
vite
構建的配置中 element-variables.scss
文件中路徑沒法解析 - 暫時引入相對路徑使用
// element-variables.scss
// $--font-path: '~element-plus/lib/theme-chalk/fonts';
$--font-path: '../node_modules/element-plus/lib/theme-chalk/fonts';
// @import "~element-plus/packages/theme-chalk/src/index.scss";
@import '../node_modules/element-plus/packages/theme-chalk/src/index.scss';
複製代碼
optimizeDeps: {
include: ['element-plus/lib/locale/lang/zh-cn'],
}
複製代碼
axios封裝
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import storage from '../utils/storage'
import { get } from 'lodash'
import { useRouter } from 'vue-router'
const router = useRouter()
const request = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_URL,
timeout: 10000,
})
const errorHandler = (error: any) => {
const status = get(error, 'response.status')
switch (status) {
case 400:
error.message = '請求錯誤'
break
case 401:
error.message = '未受權,請登陸'
router.push('/login')
storage().remove('ACCESS_TOKEN')
break
case 403:
error.message = '拒絕訪問'
break
case 404:
error.message = `請求地址出錯: ${error.response.config.url}`
break
case 408:
error.message = '請求超時'
break
case 500:
error.message = '服務器內部錯誤'
break
case 501:
error.message = '服務未實現'
break
case 502:
error.message = '網關錯誤'
break
case 503:
error.message = '服務不可用'
break
case 504:
error.message = '網關超時'
break
case 505:
error.message = 'HTTP版本不受支持'
break
default:
break
}
return Promise.reject(error)
}
request.interceptors.request.use((config: AxiosRequestConfig) => {
config.headers.Authorization = storage().get('ACCESS_TOKEN')
return config
}, errorHandler)
request.interceptors.response.use((response: AxiosResponse) => {
if (response.headers.authorization) {
storage().set('ACCESS_TOKEN', response.headers.authorization)
}
const dataAxios = response.data
const { code } = dataAxios
if (code === undefined) {
return dataAxios
} else {
switch (code) {
case 0:
return dataAxios.data
default:
return dataAxios.message
}
}
}, errorHandler)
export default request
複製代碼
interface ImportMetaEnv {
VITE_APP_BASE_URL?: string
}
複製代碼
緩存封裝
class localStorageAPI {
set(key: string, value: string): void {
try {
localStorage.setItem(key, value)
} catch (e) {
if (e.name === 'QuotaExceededError') {
throw new Error('Out of Memory Limit Localstorage')
} else {
throw new Error(e.name)
}
}
}
get(key: string): string {
return localStorage.getItem(key) || ''
}
remove(key: string): void {
localStorage.removeItem(key)
}
setExpire(key: string, value: string, expire: number): void {
const curTime = new Date().getTime()
return this.set(key, JSON.stringify({ val: value, time: curTime + expire }))
}
getExpire(key: string): string {
const val: string = this.get(key)
const dataObj = JSON.parse(val)
if (new Date().getTime() - dataObj.time < 0) {
return dataObj.val
} else {
return ''
}
}
}
export { localStorageAPI }
複製代碼
class SessionstorageAPI {
set(key: string, value: string): void {
return sessionStorage.setItem(key, value)
}
get(key: string): string {
return sessionStorage.getItem(key) || ''
}
remove(key: string): void {
return sessionStorage.removeItem(key)
}
}
export { SessionstorageAPI }
複製代碼
import { localStorageAPI } from './localstorage'
import { SessionstorageAPI } from './sessionstorage'
interface UseStoreType {
set: Function
get: Function
remove: Function
getExpire?: Function
setExpire?: Function
}
export default (store?: string): UseStoreType => {
let UseStore
switch (store) {
case 'localstorage':
UseStore = localStorageAPI
break
case 'sessionstorage':
UseStore = SessionstorageAPI
break
default:
UseStore = localStorageAPI
break
}
return new UseStore()
}
複製代碼
全局樣式
/style/reset.less
- 主要是滾動條樣式
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
font-size: 14px;
}
div {
box-sizing: border-box;
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: #f5f5f5;
}
::-webkit-scrollbar-track {
border: none;
background-color: #fff;
}
::-webkit-scrollbar-thumb {
border-radius: 4px;
background-color: rgba(144, 147, 153, 0.3);
cursor: pointer;
}
複製代碼
環境變量
.env.development
.env.production
# .env.development
VITE_APP_BASE_URL=/api
複製代碼
# .env.production
VITE_APP_BASE_URL=/
複製代碼
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
const pathResolve = (pathStr: string): string => {
return resolve(__dirname, '.', pathStr)
}
export default defineConfig({
alias: {
'@': pathResolve('./src'),
},
server: {
open: false,
https: false,
proxy: {
'/api': {
target: 'http://',
changeOrigin: true,
ws: false,
secure: false,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
hmr: {
overlay: true,
},
},
build: {
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
rollupOptions: {
output: {
manualChunks: {},
},
},
chunkSizeWarningLimit: 800,
},
plugins: [vue()],
optimizeDeps: {
include: ['element-plus/lib/locale/lang/zh-cn'],
},
})
複製代碼