前言
记录一下使用 Vite 创建 Vue3+TS 项目并整合 ElementPlus、Axios、Pinia、Less、Vue-router 等组件或插件。
一、使用 Vite 创建 Vue3+TS 项目
1.新建一个 temp 文件夹
(1)在桌面新建一个 temp 文件夹,然后在 VS Code 中打开此文件夹,打开一个终端;
2.创建一个 Vue3 项目工程
(1)具体操作如下:
npm create vite@latest
(1) 输入项目名,如: vite-vue3-ts-less-element_plus ,然后回车
? Project name: >> vite-vue3-ts-less-element_plus
(2) 选择 Vue 框架,回车
? Select a framework: >> - Use arrow-keys. Return to submit.
Vanilla
> Vue
React
Preact
Lit
Svelte
Others
(3) 选择数据类型,回车
? Select a variant: >> - Use arrow-keys. Return to submit.
> TypeScript
JavaScript
Customize with create-vue ↗
Nuxt ↗
(4) 创建完成,运行项目
Done. Now run:
cd vite-vue3-ts-less-element_plus
npm install
npm run dev
PS C:\Users\Administrator\Desktop\temp>
二、解决一下配置问题
1.修改配置文件
(1)修改【vite.config.ts】文件
修改前:
import {
defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
})
修改后:
import {
defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import {
resolve } from 'path'
/**
* 详情见 vitejs 文档:https://vitejs.dev/config/
*/
export default defineConfig({
plugins: [vue()],
base: '/xxx/', // 配置相对地址或绝对地址,此处应为绝对地址,若将 Web 部署到 Nginx 所在的目录为 nginx-1.17.8/html/xxx ,则这个 base 的值就为 /xxx/
resolve: {
alias: {
'@': resolve(__dirname, './src'),
assets: resolve(__dirname, './src/assets'),
}
},
server: {
host: '', // 主机
port: 5173, // 端口
proxy: {
// 项目 v1 的服务端接口地址
'/v1/api': {
target: 'http://127.0.0.1:8091/',
changeOrigin: true,
secure: false,
ws: true
},
// 项目 v2 的服务端接口地址
'/v2/api': {
target: 'http://127.0.0.1:8092/',
changeOrigin: true,
secure: false,
ws: true
},
// 项目 v3 的服务端接口地址
'/v3/api': {
target: 'http://127.0.0.1:8093/',
changeOrigin: true,
secure: false,
ws: true
},
// // 默认服务端接口地址
// '/': {
// target: 'http://127.0.0.1:8090/',
// changeOrigin: true,
// secure: false,
// ws: false
// }
}
}
})
(2)修改【tsconfig.json】文件
修改前:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{
"path": "./tsconfig.node.json" }]
}
修改后:
{
"compilerOptions": {
"allowJs": true, // xxx.vue is a JavaScript file. Did you mean to enable the 'allowJs' option?
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Node",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{
"path": "./tsconfig.node.json" }]
}
(3)修改【tsconfig.node.json】文件
修改前:
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
修改后:
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
2.解决报错问题
(1)找不到名称"__dirname"。
原因:path 模块是 node.js 的内置模块,而 node.js 默认不支持 ts 文件的
解决:安装 【@type/node】 依赖包【npm install @types/node --save-dev】
(2)未设置 "baseUrl" 时,不允许使用非相对路径。是否忘记了前导 "./"?。
解决:在【tsconfig.json】文件添加【baseUrl】配置
{
"compilerOptions": {
...
"baseUrl": ".", // 未设置 "baseUrl" 时,不允许使用非相对路径。
"paths": {
"@": ["src"],
"@/*": ["src/*"]
}
},
...
}
(3)找不到模块"./App.vue"或其相应的类型声明。
解决:在【src】目录新建【shims-vue.d.ts】文件,文件内容为以下代码
/* eslint-disable */
declare module '*.vue' {
import type {
DefineComponent } from 'vue'
const component: DefineComponent<{
}, {
}, any>
export default component
}
(4)Vite 项目如何配置相对地址或绝对地址?
解决:在【vite.config.ts】文件中加上【base】属性,值可以为相对地址【'./'】,也可以为绝对地址【'/xxx/'】
export default defineConfig({
plugins: [vue()],
base: '/xxx/', // 配置相对地址或绝对地址,此处应为绝对地址,若将 Web 部署到 Nginx 所在的目录为 nginx-1.17.8/html/xxx ,则这个 base 的值就为 /xxx/
resolve: {
alias: {
'@': resolve(__dirname, './src'),
assets: resolve(__dirname, './src/assets'),
}
},
})
(5)当【npm run build】打包时,报错,提示信息为【Did you mean to enable the 'allowJs' option?】
解决:在【tsconfig.json】文件增加 allowJs 配置
{
"compilerOptions": {
"allowJs": true, // xxx.vue is a JavaScript file. Did you mean to enable the 'allowJs' option?
// ...
}
}
(6)因项目未指定 ESlint 解析器,导致一些语法解析错误
解决:项目根目录新建【.eslintrc.js】文件,注意文件名开头有个点,然后就完美解决
module.exports = {
env: {
browser: true,
es2020: true,
node: true,
},
extends: ["plugin:vue/vue3-recommended", "plugin:prettier/recommended"],
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser", // 指定ESlint的解析器
sourceType: "module",
},
plugins: ["vue", "@typescript-eslint", "prettier"],
rules: {
"prettier/prettier": "error",
},
}
三、整合 ElementPlus 组件库
(1)具体操作如下:
第一步:导入依赖包
npm i element-plus -D
第二步:在项目的 src 目录新建 plugins 文件夹,里面再新建 element-plus.ts 文件,写入以下代码
import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn' // 汉化 element-plus 组件
export default (app: any) => {
app.use(ElementPlus, {
locale: zhCn,
})
}
第三步:在项目的 main.ts 文件夹引入和使用该插件和注册图标,即整合完成,main.ts 文件如下所示
import {
createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App)
// 引入 ElementPlus 插件(npm i element-plus)
import ElementPlusPlugin from '@/plugins/element-plus'
// 全局注册 ElementPlus 图标组件(npm install @element-plus/icons-vue)
import * as ElementPlusIcons from '@element-plus/icons-vue'
for(const [key, component] of Object.entries(ElementPlusIcons)) {
app.component(key, component)
}
app
.use(store)
.use(router)
.use(ElementPlusPlugin)
.mount('#app')
第四步:验证整合成功,在项目的 App.vue 文件夹,例如写个按钮标签,保存即可看到效果,App.vue 文件如下所示
<template>
<div style="display: flex; padding: 100px; align-item: center;">
<el-button size="small" type="primary" icon="UploadFilled" @click="void (0)">
点击事件
</el-button>
<el-button size="small" type="primary" plain @click="void (0)">
<el-icon :size="18">
<UploadFilled />
</el-icon>
<span>点击事件</span>
</el-button>
<el-button size="small" type="primary" circle>
<el-icon :size="18">
<UploadFilled />
</el-icon>
</el-button>
<el-icon :size="20" style="color: #409eff; cursor: pointer" @click="void (0)">
<UploadFilled />
</el-icon>
</div>
</template>
<style lang="less">
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: none;
}
#app {
width: 100%;
height: 100%;
}
</style>
四、封装并使用 Axios 插件
(1)导入相关依赖,封装 axios 工具并且使用;
第一步:导入 axios 和 nprogress 依赖包
npm i axios
npm i nprogress
npm i --save-dev @types/nprogress
第二步:在 src 目录新建 utils 文件夹,再新建 requestUtil.ts 文件,写上以下代码
import axios from 'axios'
import Nprogress from 'nprogress'
import 'nprogress/nprogress.css'
import {
ElMessage } from 'element-plus'
const http = axios.create({
baseURL: '',
timeout: 300 * 1000, // 请求超时时间设置为300秒
})
const NETWORK_ERROR = '网络错误,请联系开发人员'
/**
* 请求拦截器
*/
http.interceptors.request.use((req) => {
console.log('请求拦截器 =>', req)
Nprogress.start()
return req;
}, (error) => {
Nprogress.done()
return Promise.reject(error);
});
/**
* 响应拦截器
*/
http.interceptors.response.use(function (res) {
console.log('响应拦截器 =>', res)
Nprogress.done()
if (res.status == 200) {
return res.data
} else {
ElMessage.error((NETWORK_ERROR))
return Promise.reject(NETWORK_ERROR)
}
});
export default http
第三步:在 src 目录新建 api 文件夹,里面再新建 UserManage 文件夹,里面再新建 index.ts 文件,写上以下代码
import http from '@/utils/requestUtil'
export default {
/**
* 根据用户ID查询用户信息
* 请服务端先准备好此接口:http://localhost:8080/v1/api/getUserById?userId=10001
*/
getUserById(userId: any) {
return http.get(`/v1/api/getUserById?userId=${
userId}`)
},
/**
* 保存用户信息
*/
saveUser(data: any) {
return http.post(
'/v1/api/saveUser',
data,
{
headers: {
'Content-Type': 'application/json'
},
}
)
},
}
第四步:在 main.ts 文件引入HTTP请求工具并配置为全局方法
// 引入HTTP请求工具并配置为全局方法
import axios from 'axios'
import UserManage_Api from '@/api/UserManage/index'
app.config.globalProperties.$http = {
...UserManage_Api,
}
app.config.globalProperties.$axios = axios
(2)接口请求示例,在 App.vue 文件加上接口请求代码,如下所示;
<template>
<div style="display: flex; padding: 100px; align-item: center;">
<el-button size="small" type="primary" icon="UploadFilled" @click="void (0)">
点击事件
</el-button>
<el-button size="small" type="primary" plain @click="void (0)">
<el-icon :size="18">
<UploadFilled />
</el-icon>
<span>点击事件</span>
</el-button>
<el-button size="small" type="primary" circle>
<el-icon :size="18">
<UploadFilled />
</el-icon>
</el-button>
<el-icon :size="20" style="color: #409eff; cursor: pointer" @click="void (0)">
<UploadFilled />
</el-icon>
</div>
</template>
<script>
export default {
data: () => ({
content: ''
}),
created() {
this.getUserById(10001)
},
methods: {
/**
* 根据用户ID查询用户信息
*/
async getUserById(userId) {
// http://127.0.0.1:8080/v1/api/getUserById?userId=10001
const res = await this.$http.getUserById(userId)
console.log(res)
},
}
}
</script>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: none;
}
#app {
width: 100%;
height: 100%;
}
</style>
五、整合 vue-router、pinia、less 等插件
1.安装较新版本的 vue-router 路由插件
(1)使用方式和以前一样
npm view vue-router versions --json
npm i vue-router@4.2.0
2.安装 pinia 插件
(1)听说 Vuex 拥抱 ts 没有 Pinia 好,详情使用方式见官网(Pinia 中文文档)
npm i pinia
(2)在 src 目录新建 store 文件夹,再新建 index.ts 文件, 文件内容如下
import {
createPinia } from 'pinia'
const store = createPinia()
export default store
(3)再新建 ILoveYouStore 文件,文件内容如下
import {
defineStore } from 'pinia'
/**
* 爱老虎油状态管理仓库
*/
export const ILoveYouStore = defineStore({
id: 'ILoveYouStore', // ID必填且唯一
state: () => {
return {
xxx: 'Hello,World!',
yyy: 520,
}
},
getters: {
},
actions: {
setXxx(xxx: string) {
this.xxx = xxx
},
}
})
(4) 如下为在某个 vue 页面,简单使用 pinia 状态管理仓库
<script>
// 引入爱老虎油状态管理仓库
import {
ILoveYouStore } from '@/store/ILoveYouStore'
const useILoveYouStore = ILoveYouStore()
</script>
然后随便用Vue2、Vue3、Vue3+语法糖来定义数据
<!-- ^ Vue2 -->
<template>
<div v-if="useILoveYouStore.$state.xxx != null">{
{
useILoveYouStore.$state.xxx }}</div>
<div v-else>{
{
useILoveYouStore.$state }}</div>
</template>
<script>
export default {
data: () => ({
useILoveYouStore: useILoveYouStore,
}),
}
</script>
<!-- / Vue2 -->
<!-- ^ Vue3 -->
<script>
import {
ref } from 'vue';
export default {
setup() {
const useILoveYouStore = useILoveYouStore
return {
useILoveYouStore }
},
}
</script>
<!-- / Vue3 -->
<!-- ^ Vue3+语法糖 -->
<script setup>
const useILoveYouStore = useILoveYouStore
</script>
<!-- / Vue3+语法糖 -->
3.安装 less 插件
(1)导入依赖后,就可以在页面任意使用了
npm i less -D
以上部分内容借鉴其他文章。