个人使用vue vite ts创建项目时笔记以及相关插件的使用汇总。
npm init vite@latest system-vue -- --template vue-ts
cd system-vue
npm install
npm run dev
.env.development
ENV = 'development'
VITE_TITLE = '开发环境'
VITE_BASE_URL = 'http://127.0.0.1:8080'
VITE_BASE_API = '/api'
.env.production
ENV = 'production'
VITE_TITLE = '生产环境'
VITE_BASE_URL = ''
VITE_BASE_API = ''
.env.test
ENV = 'test'
VITE_TITLE = '测试环境'
VITE_BASE_URL = ''
VITE_BASE_API = ''
为保证node使用建议安装
@types/node
npm install @types/node --save-dev
// vite.config.ts
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import * as path from 'path'
export default defineConfig({
plugins: [
vue()
],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@views': path.resolve(__dirname, 'src/views'),
'@layout': path.resolve(__dirname, 'src/layout'),
'@components': path.resolve(__dirname, 'src/components')
}
},
server: {
host: '127.0.0.1',
port: 3000,
cors: true,
open: false,
proxy: {
'/api': {
target: 'http://127.0.0.1:8080',
changeOrigin: true,
rewrite: (path: string) => path.replace(/^/api/, '')
}
}
}
})
解决打包错误
package.json
{
"script": {
"build": "vue-tsc --noEmit --skipLibCheck && vite build"
}
}
配置
tsconfig.json
{
"compilerOptions": {
"jsx": "preserve",
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"sourceMap": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"useDefineForClassFields": true,
"lib": [
"esnext",
"dom"
],
"types": [
"node",
"vite/client"
]
},
"skipLibCheck": true,
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"baseUrl": ".",
"paths": {
"@": [
"src"
]
},
"exclude": [
"node_modules"
],
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
"vite.config.ts"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}
npm install eslint eslint-plugin-vue --save-dev
# 由于ESLint默认使用Espree语法解析,是不能识别TypeScript某些语法,所以需安装@typescript-eslint/parser替换掉默认解析器
npm install @typescript-eslint/parser --save-dev
# 补充额外得typescript语法的规则
npm install @typescript-eslint/eslint-plugin --save-dev
.eslintrc.js
或.eslintrc.json
// .eslintrc.js
module.exports = {
root: true,
env: {
node: true,
es6: true,
browser: true
},
extends: [
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'eslint:recommended'
],
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: '8',
sourceType: 'module',
ecmaFeatures: {
jsx: true
}
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'indent': 0,
'space-before-function-paren': 0
}
}
.eslintignore
index.html
dist
node_modules
*.md
.vscode
.idea
public
# less
npm install less less-loader -D
# sass
npm install sass sass-loader -D
npm install vue-router@4
// src/router/index.ts
import {createRouter, createWebHistory, RouteRecordRaw} from 'vue-router'
const routes: Array = [
{
path: '/',
redirect: '/login'
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('../views/error/404.vue')
},
{
path: '/login',
name: 'login',
meta: {
title: '登录',
keepAlive: true,
requireAuth: false
},
component: () => import('@views/login.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
router.beforeEach((to, from, next) => {
next()
})
router.afterEach(() => {
})
export default router
// main.ts
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
.mount('#app')
npm install nprogress --save
// 在src/router/index.ts中添加下列配置
import * as nProgress from 'nprogress'
router.beforeEach((to, from, next) => {
nProgress.start()
next()
})
router.afterEach(() => {
nProgress.done()
})
nProgress.configure({
ease: 'linear',
speed: 500,
showSpinner: false // 是否使用进度环
})
// 在mian.ts中引入样式
import 'nprogress/nprogress.css'
// App.vue
解决引用错误问题
// 在env.d.ts中添加
declare module 'nprogress'
# element plus
npm install element-plus --save
# element plus icon
npm install @element-plus/icons-vue
// src/plugins/element-plus.ts
import {App} from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import locale from 'element-plus/es/locale/lang/zh-cn'
import * as Icons from '@element-plus/icons-vue'
export default {
install(app: App) {
app.use(ElementPlus, {
locale,
size: 'small' || 'default' || 'large'
})
Object.keys(Icons).forEach((key: string) => {
app.component(key, Icons[key as keyof typeof Icons]);
})
}
}
// main.ts
import {createApp} from 'vue'
import App from './App.vue'
import ElementPlus from './plugins/element-plus'
const app = createApp(App)
app.use(ElementPlus)
.mount('#app')
新建
src\assets\style\global.scss
样式文件
/*全局公共样式表*/
html, body, #app {
margin: 0;
padding: 0;
height: 100%;
font-family: Avenir, Helvetica, Arial, sans-serif;
a {
text-decoration: none;
color: #333;
}
ul, li {
list-style: none;
}
}
/*设置滚动条样式*/
::-webkit-scrollbar {
width: 5px;
}
/*定义滚动条轨道 内阴影+圆角*/
::-webkit-scrollbar-track {
border-radius: 10px;
background-color: rgba(0, 0, 0, 0.1);
}
/*定义滑块 内阴影+圆角*/
::-webkit-scrollbar-thumb {
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(26, 25, 25, 0.3);
background-color: rgba(0, 0, 0, 0.1);
}
/*设置进度条颜色 不配置时为默认颜色*/
#nprogress .bar {
/*background: rgba(41, 236, 127, 0.5) !important;*/
}
// APP.vue
@import 'assets/style/global.scss';
npm install reset.css --save
// APP.vue
@import 'reset.css';
npm install animate.css --save
// APP.vue
@import 'animate.css';
通过class 使用详情
An animated element
官网:Windi Css
npm install -D vite-plugin-windicss windicss
// 在vite.config.ts中添加下列配置
import WindiCSS from 'vite-plugin-windicss'
export default {
plugins: [
WindiCSS(),
],
}
// 在main.ts中引入样式文件
import 'virtual:windi.css'
使用详情
npm install axios --save
// src/utils/axios.ts
import axios, {AxiosRequestConfig, AxiosResponse} from 'axios'
import {ElMessage, ElNotification} from 'element-plus'
import {useRouter} from 'vue-router'
import * as nProgress from 'nprogress'
import {useMainStore} from '../store'
axios.create({
baseURL: import.meta.env.VITE_BASE_URL,
timeout: 5000,
withCredentials: true
})
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=utf-8';
axios.interceptors.request.use((config: AxiosRequestConfig) => {
nProgress.start()
if (useMainStore().getAuthorization && localStorage.getItem('Authorization')) {
if (config.headers) {
config.headers.Authorization = useMainStore().getAuthorization
}
}
return config;
}, ((error: any) => {
ElNotification.error('请求错误!')
return Promise.reject(error);
}))
axios.interceptors.response.use((response: AxiosResponse) => {
nProgress.done()
switch (response.status as number) {
case 401: {
ElMessage.warning('请先登录')
const router = useRouter()
router.push('/login')
break
}
case 403: {
ElMessage.warning('拒绝访问')
break
}
}
return response;
}, ((error: any) => {
ElNotification.error('响应错误!')
return Promise.reject(error);
}
))
export default axios
// api/user/user.ts
import axios from '../../utils/axios'
import * as qs from 'qs'
const baseAPI = import.meta.env.VITE_BASE_API
export const login = (data: any) => {
return axios({
method: 'POST',
url: baseUrl + '/login',
data: qs.stringify(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
}
npm install pinia
// store/index.ts
import {defineStore} from 'pinia'
interface storeTypes {
}
export const useMainStore = defineStore('main', {
// 存储全局状态
state: (): storeTypes => {
return {}
},
// 封装计算属性 具有缓存功能
getters: {},
// 封装业务逻辑 修改state
actions: {}
})
// main.ts
import {createApp} from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
const app = createApp(App)
app.use(createPinia())
.mount('#app')
什么是
i18n
?
i18n
(internationalization)是“国际化”的简称。由于其首尾分别为 i 和 n ,中间有18 个字符。故简写为 i18n
。在vue.js中,有vue i18n国际化插件。可以轻松实现项目国际化的操作。
如何使用
i18n
?
i18n
插件npm install vue-i18n
中文语言文件:
zh_CN
英文语言文件:en.ts
1.文件en.ts
// src/i18n/language/en.ts
export default {
system: {
title: 'test i18n'
}
}
2.文件zh_CN.ts
// src/i18n/language/zh_CN.ts
export default {
system: {
title: '测试 i18n'
}
}
index.ts
// src/i18n/index.ts
import {createI18n} from 'vue-i18n'
import zh_CN from './language/zh_CN'
import en from './language/en'
const messages = {
zh_CN: {...zh_CN},
en: {...en}
}
// 获取浏览器当前语言
const getCurrentLanguage = () => {
const language = navigator.language
const currentLanguage = language.indexOf('zh') !== -1 ? 'zh_CN' : 'en'
localStorage.setItem('language', currentLanguage)
return currentLanguage
}
// 创建i18n实例
const i18n = createI18n({
legacy: false,
globalInjection: true,
locale: localStorage.getItem('language') || getCurrentLanguage() || 'zh_CN',
messages: messages
})
export default i18n
import {createApp} from 'vue'
import App from './App.vue'
import i18n from './i18n'
const app = createApp(App)
app.use(i18n)
.mount('#app')
切换语言
中 文
English
{{ $t(`system.title`) }}
VueUse
是一个基于Composition API
的实用函数集合。
npm install @vueuse/core
更多使用请访问:vueUse
鼠标坐标:{{x}},{{y}}
// prettier.config.js
module.exports = {
semi: false,
singleQuot: true,
trailingComma: "none",
printWidth: 100,
vueIndentScriptAndStyle: true,
singleQuote: true,
proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict',
endOfLine: 'auto',
}
.prettierignore
/node_modules/**
/public/*
npm install qs
import * as qs from 'qs'
解决引用报红
// env.d.ts
declare module 'qs'
# 由于universal-cookie依赖于vueuse/integrations 故需要安装
npm install @vueuse/integrations
# cookie依赖安装
npm install universal-cookie
import {useCookies} from '@vueuse/integrations/useCookies'
npm install @vueuse/core
import { Ref, ref } from 'vue'
import { useBase64 } from '@vueuse/core'
const text = ref('')
const { base64 } = useBase64(text)
npm install vite-plugin-svg-icons -D
// src/components/svgIcon/index.vue
// vite.config.ts
import {defineConfig} from 'vite'
import * as path from 'path'
import {createSvgIconsPlugin} from 'vite-plugin-svg-icons'
export default defineConfig({
plugins: [
createSvgIconsPlugin({
// svg图标存放路径
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons/svg')],
symbolId: 'icon-[dir]-[name]'
})
]
})
import {createApp} from 'vue'
import App from './App.vue'
import 'virtual:svg-icons-register'
import svgIcon from '@components/svgIcon/index.vue'
const app = createApp(App)
app .component('svg-icon', svgIcon)
.mount('#app')