当前位置:   article > 正文

使用 Vite 创建 Vue3+TS 项目并整合 ElementPlus、Axios、Pinia、Less、Vue-router 等组件或插件_vite vue3 elementplus ts

vite vue3 elementplus ts

前言

记录一下使用 Vite 创建 Vue3+TS 项目并整合 ElementPlus、Axios、Pinia、Less、Vue-router 等组件或插件。

一、使用 Vite 创建 Vue3+TS 项目

1.新建一个 temp 文件夹

(1)在桌面新建一个 temp 文件夹,然后在 VS Code 中打开此文件夹,打开一个终端;

2.创建一个 Vue3 项目工程

(1)具体操作如下:

  1. npm create vite@latest
  2. (1) 输入项目名,如: vite-vue3-ts-less-element_plus ,然后回车
  3. ? Project name: » vite-vue3-ts-less-element_plus
  4. (2) 选择 Vue 框架,回车
  5. ? Select a framework: » - Use arrow-keys. Return to submit.
  6. Vanilla
  7. > Vue
  8. React
  9. Preact
  10. Lit
  11. Svelte
  12. Others
  13. (3) 选择数据类型,回车
  14. ? Select a variant: » - Use arrow-keys. Return to submit.
  15. > TypeScript
  16. JavaScript
  17. Customize with create-vue ↗
  18. Nuxt
  19. (4) 创建完成,运行项目
  20. Done. Now run:
  21. cd vite-vue3-ts-less-element_plus
  22. npm install
  23. npm run dev
  24. PS C:\Users\Administrator\Desktop\temp>

二、解决一下配置问题

1.修改配置文件

(1)修改【vite.config.ts】文件

修改前:

  1. import { defineConfig } from 'vite'
  2. import vue from '@vitejs/plugin-vue'
  3. // https://vitejs.dev/config/
  4. export default defineConfig({
  5. plugins: [vue()],
  6. })

修改后:

  1. import { defineConfig } from 'vite'
  2. import vue from '@vitejs/plugin-vue'
  3. import { resolve } from 'path'
  4. /**
  5. * 详情见 vitejs 文档:https://vitejs.dev/config/
  6. */
  7. export default defineConfig({
  8. plugins: [vue()],
  9. base: '/xxx/', // 配置相对地址或绝对地址,此处应为绝对地址,若将 Web 部署到 Nginx 所在的目录为 nginx-1.17.8/html/xxx ,则这个 base 的值就为 /xxx/
  10. resolve: {
  11. alias: {
  12. '@': resolve(__dirname, './src'),
  13. assets: resolve(__dirname, './src/assets'),
  14. }
  15. },
  16. server: {
  17. host: '', // 主机
  18. port: 5173, // 端口
  19. proxy: {
  20. // 项目 v1 的服务端接口地址
  21. '/v1/api': {
  22. target: 'http://127.0.0.1:8091/',
  23. changeOrigin: true,
  24. secure: false,
  25. ws: true
  26. },
  27. // 项目 v2 的服务端接口地址
  28. '/v2/api': {
  29. target: 'http://127.0.0.1:8092/',
  30. changeOrigin: true,
  31. secure: false,
  32. ws: true
  33. },
  34. // 项目 v3 的服务端接口地址
  35. '/v3/api': {
  36. target: 'http://127.0.0.1:8093/',
  37. changeOrigin: true,
  38. secure: false,
  39. ws: true
  40. },
  41. // // 默认服务端接口地址
  42. // '/': {
  43. // target: 'http://127.0.0.1:8090/',
  44. // changeOrigin: true,
  45. // secure: false,
  46. // ws: false
  47. // }
  48. }
  49. }
  50. })

(2)修改【tsconfig.json】文件

修改前:

  1. {
  2. "compilerOptions": {
  3. "target": "ES2020",
  4. "useDefineForClassFields": true,
  5. "module": "ESNext",
  6. "lib": ["ES2020", "DOM", "DOM.Iterable"],
  7. "skipLibCheck": true,
  8. /* Bundler mode */
  9. "moduleResolution": "bundler",
  10. "allowImportingTsExtensions": true,
  11. "resolveJsonModule": true,
  12. "isolatedModules": true,
  13. "noEmit": true,
  14. "jsx": "preserve",
  15. /* Linting */
  16. "strict": true,
  17. "noUnusedLocals": true,
  18. "noUnusedParameters": true,
  19. "noFallthroughCasesInSwitch": true
  20. },
  21. "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  22. "references": [{ "path": "./tsconfig.node.json" }]
  23. }

修改后:

  1. {
  2. "compilerOptions": {
  3. "allowJs": true, // xxx.vue is a JavaScript file. Did you mean to enable the 'allowJs' option?
  4. "target": "ES2020",
  5. "useDefineForClassFields": true,
  6. "module": "ESNext",
  7. "lib": ["ES2020", "DOM", "DOM.Iterable"],
  8. "skipLibCheck": true,
  9. /* Bundler mode */
  10. "moduleResolution": "Node",
  11. "allowImportingTsExtensions": true,
  12. "resolveJsonModule": true,
  13. "isolatedModules": true,
  14. "noEmit": true,
  15. "jsx": "preserve",
  16. /* Linting */
  17. "strict": true,
  18. "noUnusedLocals": true,
  19. "noUnusedParameters": true,
  20. "noFallthroughCasesInSwitch": true
  21. },
  22. "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  23. "references": [{ "path": "./tsconfig.node.json" }]
  24. }

(3)修改【tsconfig.node.json】文件

修改前:

  1. {
  2. "compilerOptions": {
  3. "composite": true,
  4. "skipLibCheck": true,
  5. "module": "ESNext",
  6. "moduleResolution": "bundler",
  7. "allowSyntheticDefaultImports": true
  8. },
  9. "include": ["vite.config.ts"]
  10. }

修改后:

  1. {
  2. "compilerOptions": {
  3. "composite": true,
  4. "skipLibCheck": true,
  5. "module": "ESNext",
  6. "moduleResolution": "bundler",
  7. "allowSyntheticDefaultImports": true
  8. },
  9. "include": ["vite.config.ts"]
  10. }

2.解决报错问题

(1)找不到名称“__dirname”。

原因:path 模块是 node.js 的内置模块,而 node.js 默认不支持 ts 文件的

解决:安装 【@type/node】 依赖包【npm install @types/node --save-dev】

(2)未设置 "baseUrl" 时,不允许使用非相对路径。是否忘记了前导 "./"?。

解决:在【tsconfig.json】文件添加【baseUrl】配置

  1. {
  2. "compilerOptions": {
  3. ...
  4. "baseUrl": ".", // 未设置 "baseUrl" 时,不允许使用非相对路径。
  5. "paths": {
  6. "@": ["src"],
  7. "@/*": ["src/*"]
  8. }
  9. },
  10. ...
  11. }

(3)找不到模块“./App.vue”或其相应的类型声明。

解决:在【src】目录新建【shims-vue.d.ts】文件,文件内容为以下代码

  1. /* eslint-disable */
  2. declare module '*.vue' {
  3. import type { DefineComponent } from 'vue'
  4. const component: DefineComponent<{}, {}, any>
  5. export default component
  6. }

(4)Vite 项目如何配置相对地址或绝对地址?

解决:在【vite.config.ts】文件中加上【base】属性,值可以为相对地址【'./'】,也可以为绝对地址【'/xxx/'】

  1. export default defineConfig({
  2. plugins: [vue()],
  3. base: '/xxx/', // 配置相对地址或绝对地址,此处应为绝对地址,若将 Web 部署到 Nginx 所在的目录为 nginx-1.17.8/html/xxx ,则这个 base 的值就为 /xxx/
  4. resolve: {
  5. alias: {
  6. '@': resolve(__dirname, './src'),
  7. assets: resolve(__dirname, './src/assets'),
  8. }
  9. },
  10. })

(5)当【npm run build】打包时,报错,提示信息为【Did you mean to enable the 'allowJs' option?】

解决:在【tsconfig.json】文件增加 allowJs 配置

  1. {
  2. "compilerOptions": {
  3. "allowJs": true, // xxx.vue is a JavaScript file. Did you mean to enable the 'allowJs' option?
  4. // ...
  5. }
  6. }

(6)因项目未指定 ESlint 解析器,导致一些语法解析错误

解决:项目根目录新建【.eslintrc.js】文件,注意文件名开头有个点,然后就完美解决

  1. module.exports = {
  2. env: {
  3. browser: true,
  4. es2020: true,
  5. node: true,
  6. },
  7. extends: ["plugin:vue/vue3-recommended", "plugin:prettier/recommended"],
  8. parserOptions: {
  9. ecmaVersion: "latest",
  10. parser: "@typescript-eslint/parser", // 指定ESlint的解析器
  11. sourceType: "module",
  12. },
  13. plugins: ["vue", "@typescript-eslint", "prettier"],
  14. rules: {
  15. "prettier/prettier": "error",
  16. },
  17. }

三、整合 ElementPlus 组件库

(1)具体操作如下:

  1. 第一步:导入依赖包
  2. npm i element-plus -D
  3. 第二步:在项目的 src 目录新建 plugins 文件夹,里面再新建 element-plus.ts 文件,写入以下代码
  4. import ElementPlus from 'element-plus'
  5. import 'element-plus/theme-chalk/index.css'
  6. import zhCn from 'element-plus/es/locale/lang/zh-cn' // 汉化 element-plus 组件
  7. export default (app: any) => {
  8. app.use(ElementPlus, {
  9. locale: zhCn,
  10. })
  11. }
  12. 第三步:在项目的 main.ts 文件夹引入和使用该插件和注册图标,即整合完成,main.ts 文件如下所示
  13. import { createApp } from 'vue'
  14. import App from './App.vue'
  15. import router from './router'
  16. import store from './store'
  17. const app = createApp(App)
  18. // 引入 ElementPlus 插件(npm i element-plus)
  19. import ElementPlusPlugin from '@/plugins/element-plus'
  20. // 全局注册 ElementPlus 图标组件(npm install @element-plus/icons-vue)
  21. import * as ElementPlusIcons from '@element-plus/icons-vue'
  22. for(const [key, component] of Object.entries(ElementPlusIcons)) {
  23. app.component(key, component)
  24. }
  25. app
  26. .use(store)
  27. .use(router)
  28. .use(ElementPlusPlugin)
  29. .mount('#app')
  30. 第四步:验证整合成功,在项目的 App.vue 文件夹,例如写个按钮标签,保存即可看到效果,App.vue 文件如下所示
  31. <template>
  32. <div style="display: flex; padding: 100px; align-item: center;">
  33. <el-button size="small" type="primary" icon="UploadFilled" @click="void (0)">
  34. 点击事件
  35. </el-button>
  36. <el-button size="small" type="primary" plain @click="void (0)">
  37. <el-icon :size="18">
  38. <UploadFilled />
  39. </el-icon>
  40. <span>点击事件</span>
  41. </el-button>
  42. <el-button size="small" type="primary" circle>
  43. <el-icon :size="18">
  44. <UploadFilled />
  45. </el-icon>
  46. </el-button>
  47. <el-icon :size="20" style="color: #409eff; cursor: pointer" @click="void (0)">
  48. <UploadFilled />
  49. </el-icon>
  50. </div>
  51. </template>
  52. <style lang="less">
  53. * {
  54. margin: 0;
  55. padding: 0;
  56. }
  57. html, body {
  58. width: 100%;
  59. height: 100%;
  60. margin: 0;
  61. padding: 0;
  62. border: none;
  63. }
  64. #app {
  65. width: 100%;
  66. height: 100%;
  67. }
  68. </style>

四、封装并使用 Axios 插件

(1)导入相关依赖,封装 axios 工具并且使用;

  1. 第一步:导入 axios 和 nprogress 依赖包
  2. npm i axios
  3. npm i nprogress
  4. npm i --save-dev @types/nprogress
  5. 第二步:在 src 目录新建 utils 文件夹,再新建 requestUtil.ts 文件,写上以下代码
  6. import axios from 'axios'
  7. import Nprogress from 'nprogress'
  8. import 'nprogress/nprogress.css'
  9. import { ElMessage } from 'element-plus'
  10. const http = axios.create({
  11. baseURL: '',
  12. timeout: 300 * 1000, // 请求超时时间设置为300秒
  13. })
  14. const NETWORK_ERROR = '网络错误,请联系开发人员'
  15. /**
  16. * 请求拦截器
  17. */
  18. http.interceptors.request.use((req) => {
  19. console.log('请求拦截器 =>', req)
  20. Nprogress.start()
  21. return req;
  22. }, (error) => {
  23. Nprogress.done()
  24. return Promise.reject(error);
  25. });
  26. /**
  27. * 响应拦截器
  28. */
  29. http.interceptors.response.use(function (res) {
  30. console.log('响应拦截器 =>', res)
  31. Nprogress.done()
  32. if (res.status == 200) {
  33. return res.data
  34. } else {
  35. ElMessage.error((NETWORK_ERROR))
  36. return Promise.reject(NETWORK_ERROR)
  37. }
  38. });
  39. export default http
  40. 第三步:在 src 目录新建 api 文件夹,里面再新建 UserManage 文件夹,里面再新建 index.ts 文件,写上以下代码
  41. import http from '@/utils/requestUtil'
  42. export default {
  43. /**
  44. * 根据用户ID查询用户信息
  45. * 请服务端先准备好此接口:http://localhost:8080/v1/api/getUserById?userId=10001
  46. */
  47. getUserById(userId: any) {
  48. return http.get(`/v1/api/getUserById?userId=${userId}`)
  49. },
  50. /**
  51. * 保存用户信息
  52. */
  53. saveUser(data: any) {
  54. return http.post(
  55. '/v1/api/saveUser',
  56. data,
  57. {
  58. headers: {
  59. 'Content-Type': 'application/json'
  60. },
  61. }
  62. )
  63. },
  64. }
  65. 第四步:在 main.ts 文件引入HTTP请求工具并配置为全局方法
  66. // 引入HTTP请求工具并配置为全局方法
  67. import axios from 'axios'
  68. import UserManage_Api from '@/api/UserManage/index'
  69. app.config.globalProperties.$http = {
  70. ...UserManage_Api,
  71. }
  72. app.config.globalProperties.$axios = axios

(2)接口请求示例,在 App.vue 文件加上接口请求代码,如下所示;

  1. <template>
  2. <div style="display: flex; padding: 100px; align-item: center;">
  3. <el-button size="small" type="primary" icon="UploadFilled" @click="void (0)">
  4. 点击事件
  5. </el-button>
  6. <el-button size="small" type="primary" plain @click="void (0)">
  7. <el-icon :size="18">
  8. <UploadFilled />
  9. </el-icon>
  10. <span>点击事件</span>
  11. </el-button>
  12. <el-button size="small" type="primary" circle>
  13. <el-icon :size="18">
  14. <UploadFilled />
  15. </el-icon>
  16. </el-button>
  17. <el-icon :size="20" style="color: #409eff; cursor: pointer" @click="void (0)">
  18. <UploadFilled />
  19. </el-icon>
  20. </div>
  21. </template>
  22. <script>
  23. export default {
  24. data: () => ({
  25. content: ''
  26. }),
  27. created() {
  28. this.getUserById(10001)
  29. },
  30. methods: {
  31. /**
  32. * 根据用户ID查询用户信息
  33. */
  34. async getUserById(userId) {
  35. // http://127.0.0.1:8080/v1/api/getUserById?userId=10001
  36. const res = await this.$http.getUserById(userId)
  37. console.log(res)
  38. },
  39. }
  40. }
  41. </script>
  42. <style>
  43. * {
  44. margin: 0;
  45. padding: 0;
  46. }
  47. html, body {
  48. width: 100%;
  49. height: 100%;
  50. margin: 0;
  51. padding: 0;
  52. border: none;
  53. }
  54. #app {
  55. width: 100%;
  56. height: 100%;
  57. }
  58. </style>

五、整合 vue-router、pinia、less 等插件

1.安装较新版本的 vue-router 路由插件

(1)使用方式和以前一样

  1. npm view vue-router versions --json
  2. npm i vue-router@4.2.0

2.安装 pinia 插件

(1)听说 Vuex 拥抱 ts 没有 Pinia 好,详情使用方式见官网(Pinia 中文文档) 

npm i pinia

(2)在 src 目录新建 store 文件夹,再新建 index.ts 文件, 文件内容如下

  1. import { createPinia } from 'pinia'
  2. const store = createPinia()
  3. export default store

(3)再新建 ILoveYouStore 文件,文件内容如下

  1. import { defineStore } from 'pinia'
  2. /**
  3. * 爱老虎油状态管理仓库
  4. */
  5. export const ILoveYouStore = defineStore({
  6. id: 'ILoveYouStore', // ID必填且唯一
  7. state: () => {
  8. return {
  9. xxx: 'Hello,World!',
  10. yyy: 520,
  11. }
  12. },
  13. getters: {
  14. },
  15. actions: {
  16. setXxx(xxx: string) {
  17. this.xxx = xxx
  18. },
  19. }
  20. })

(4) 如下为在某个 vue 页面,简单使用 pinia 状态管理仓库

  1. <script>
  2. // 引入爱老虎油状态管理仓库
  3. import { ILoveYouStore } from '@/store/ILoveYouStore'
  4. const useILoveYouStore = ILoveYouStore()
  5. </script>
  6. 然后随便用Vue2Vue3Vue3+语法糖来定义数据
  7. <!-- ^ Vue2 -->
  8. <template>
  9. <div v-if="useILoveYouStore.$state.xxx != null">{{ useILoveYouStore.$state.xxx }}</div>
  10. <div v-else>{{ useILoveYouStore.$state }}</div>
  11. </template>
  12. <script>
  13. export default {
  14. data: () => ({
  15. useILoveYouStore: useILoveYouStore,
  16. }),
  17. }
  18. </script>
  19. <!-- / Vue2 -->
  20. <!-- ^ Vue3 -->
  21. <script>
  22. import { ref } from 'vue';
  23. export default {
  24. setup() {
  25. const useILoveYouStore = useILoveYouStore
  26. return { useILoveYouStore }
  27. },
  28. }
  29. </script>
  30. <!-- / Vue3 -->
  31. <!-- ^ Vue3+语法糖 -->
  32. <script setup>
  33. const useILoveYouStore = useILoveYouStore
  34. </script>
  35. <!-- / Vue3+语法糖 -->

3.安装 less 插件

(1)导入依赖后,就可以在页面任意使用了

npm i less -D

六、项目仓库地址

到此,使用 Vite 创建 Vue3+TS 项目并整合 ElementPlus、Axios 等组件或插件的工作已全部完成,传送门如下。

vite-vue3-ts-less-element_plus: 这是一个基于 Vite 构建的 Vue3 + TS 项目,以及整合了 Less、ElementPlus 等组件或插件。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/883563
推荐阅读
相关标签
  

闽ICP备14008679号