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

前言

记录一下使用 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

六、项目仓库地址

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

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

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于使用 Vite + Vue3 + TypeScript + Pinia + Vue Router + Axios + SCSS 并自动导入 API 的设置,你可以按照以下步骤进行操作: 1. 首先,确保你已经安装了 Node.js,并且版本大于等于 12.0.0。 2. 创建一个新的 Vue 项目,可以使用 Vue CLI 或者手动创建一个空文件夹。 3. 在项目根目录下,打开终端并执行以下命令安装 Vite: ```bash npm init vite@latest ``` 按照提示选择你的项目配置,包括选择 Vue 3、TypeScript 和其他选项。 4. 进入项目目录并安装依赖: ```bash cd your-project-name npm install ``` 5. 安装 Pinia 插件: ```bash npm install pinia ``` 6. 创建一个 `src/store` 目录,并在其中创建 `index.ts` 文件,用于定义和导出你的 Pinia store。 ```typescript // src/store/index.ts import { createPinia } from 'pinia' export const store = createPinia() // 可以在这里定义你的 store 模块 ``` 7. 在项目根目录下创建 `src/api` 目录,用于存放 API 请求相关的文件。 8. 在 `src/api` 目录下创建一个 `index.ts` 文件,用于自动导入所有 API 文件。 ```typescript // src/api/index.ts const modules = import.meta.globEager('./*.ts') const apis: any = {} for (const path in modules) { if (path !== './index.ts') { const moduleName = path.replace(/^.\/|\.ts$/g, '') apis[moduleName] = modules[path].default } } export default apis ``` 这样,你就可以在 `src/api` 目录下创建各种 API 请求的文件,例如 `user.ts`: ```typescript // src/api/user.ts import axios from 'axios' export function getUser(id: number) { return axios.get(`/api/user/${id}`) } ``` 然后,在你的组件使用自动导入的 API: ```typescript import { defineComponent, ref } from 'vue' import { useUserStore } from '@/store' import apis from '@/api' export default defineComponent({ setup() { const userStore = useUserStore() const userId = ref(1) const fetchUser = async () => { const response = await apis.user.getUser(userId.value) userStore.setUser(response.data) } return { userId, fetchUser, } }, }) ``` 以上就是使用 Vite + Vue3 + TypeScript + Pinia + Vue Router + Axios + SCSS 并自动导入 API 的基本设置。你可以根据自己的需求进一步配置和扩展。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值