vite4 + vue3 + axios + pinia + vue 您所在的位置:网站首页 ts版本红利 vite4 + vue3 + axios + pinia + vue

vite4 + vue3 + axios + pinia + vue

2023-03-21 12:25| 来源: 网络整理| 查看: 265

安装node

下载node软件安装,Vite 需要Node.js版本 14.18+,16+

安装vitenpm create vite@latest安装项目npm create vite@latest my-vue-app -- --template vue项目结构相关项目配置

package.json

{ "name": "my-vue-app", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc && vite build", "preview": "vite preview", "test": "vitest", "coverage": "vitest run --coverage" }, "dependencies": { "vue": "^3.2.45" }, "devDependencies": { "@vitejs/plugin-vue": "^4.0.0", "@vitest/coverage-c8": "^0.29.2", "@vue/test-utils": "^2.3.0", "axios": "^1.3.4", "element-plus": "^2.2.32", "jsdom": "^21.1.0", "path": "^0.12.7", "pinia": "^2.0.32", "pinia-plugin-persist": "^1.0.0", "sass": "^1.58.3", "typescript": "^4.9.3", "unplugin-auto-import": "^0.15.0", "unplugin-vue-components": "^0.24.0", "vite": "^4.1.0", "vite-plugin-compression": "^0.5.1", "vite-plugin-style-import": "^2.0.0", "vitest": "^0.29.2", "vue-router": "^4.1.6", "vue-tsc": "^1.0.24" } }

vite.config.ts

(包括element-plus按需引入及主题色改变,vitest的配置)

/// import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue' import { resolve } from "path" import viteCompression from 'vite-plugin-compression'; import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'; // https://vitejs.dev/config/ export default defineConfig({ base: '/', plugins: [ // css主题色改变 createStyleImportPlugin({ resolves: [ElementPlusResolve()], libs: [ { libraryName: 'element-plus', esModule: true, resolveStyle: (name) => { return `element-plus/theme-chalk/${name}.css` }, }, ] }), vue(), AutoImport({ resolvers: [ElementPlusResolver({ // 自动引入修改主题色添加这一行,使用预处理样式,不添加将会导致使用ElMessage,ElNotification等组件时默认的主题色会覆盖自定义的主题色 importStyle: "sass", })], }), Components({ resolvers: [ElementPlusResolver({ // 自动引入修改主题色添加这一行,使用预处理样式 importStyle: "sass", })], }), viteCompression() // gzip压缩 ], css: { preprocessorOptions: { scss: { // 自定义的主题色 additionalData: `@use "@/assets/ele.scss" as *;`, }, }, }, server: { proxy: { '/api': { target: 'http://localhost:1111', //实际请求地址 changeOrigin: true, }, } }, resolve: { // ↓路径别名 alias: { "@": resolve(__dirname, "./src") } }, build: { rollupOptions: { // 安全问题,打包的文件名要混淆 output: { chunkFileNames: 'static/js/[hash].js', entryFileNames: 'static/js/[hash].js', assetFileNames: 'static/[ext]/[hash].[ext]', } } }, test: { globals: true, environment: "jsdom", transformMode: { web: [/.[tj]sx$/] } } })

tsconfig.json

{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "moduleResolution": "Node", "strict": true, "jsx": "preserve", "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "lib": [ "ESNext", "DOM" ], "skipLibCheck": true, "noEmit": true, "baseUrl": "./", "paths": { "@/*": [ "./src/*" ] }, "types": ["vitest/globals"] }, "include": [ "src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*/.vue" ], "references": [ { "path": "./tsconfig.node.json" } ] }

src/main.ts

import { createApp } from 'vue' import App from './App.vue' import router from './router' import { createPinia } from 'pinia' import piniaPluginPersist from 'pinia-plugin-persist' import ElementPlus from 'element-plus' const app = createApp(App) app.use(ElementPlus).use(createPinia().use(piniaPluginPersist)).use(router).mount('#app')

src/assets/ele.scss

// styles/element/index.scss /* just override what you need */ @forward 'element-plus/theme-chalk/src/common/var.scss' with ( $colors: ( 'primary': ( 'base': green, ), ) ); // If you just import on demand, you can ignore the following content. // if you want to import all styles: // @use "element-plus/theme-chalk/src/index.scss" as *;vue-router

引用见上文 src/main.ts 文件

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router' const routes:Array = [ { path: '/Login', name: 'Login', component: () => import('@/views/Login.vue') }, { path: '/', name: 'Main', component: () => import('@/views/Main.vue'), children: [ { path: '/List', name: 'List', component: () => import('@/views/List.vue') } ] }, ] const router = createRouter({ history: createWebHistory(), routes }) export default router

src/App.vue

import { ref } from "vue"; const a = ref(null) @import url("@/assets/common.scss"); body, #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; display: flex; margin: 0; padding: 0; position: absolute; width: 100%; height: 100%; min-width: 1080px; } .app { width: 100%; height: 100%; min-width: 1080px; } pinia (vuex5.0)

用于axios部分,多请求loading处理

src/store/api.ts

import { defineStore } from 'pinia' export const useApiStore = defineStore('api', { state: () => ({ loadingCount: 0, // 请求数量统计 }), persist: { enabled: true, strategies: [ { storage: sessionStorage, paths: [] }, ], }, actions: { /** * 请求数量增加 * @param {*} state * @returns */ addLoadingCount: (state: any) => state.loadingCount++, /** * 请求数量减少 * @param {*} state * @returns */ reduceLoadingCount: (state: any) => state.loadingCount--, /** * 请求数量重置 * @param {*} state * @returns */ resetLoadingCount: (state: any) => state.loadingCount = 0, }, })axios

封装加入多请求loading处理。loading用的是element-plus的loading

src/api/index.ts

import axios, { AxiosResponse, AxiosError } from 'axios' import { ElLoading, ElMessage } from 'element-plus' import { useApiStore } from '../store/api' const apiStore = useApiStore(); axios.interceptors.request.use( config => { config.baseURL = "/" if (config.method == 'get') { config.headers['Content-Type'] = 'application/x-www-form-urlencoded'; } if (config.method == 'post') { config.headers['Content-Type'] = 'application/json'; } return config; }, err => { return Promise.reject(err) } ); let loadingInstance: any = null function showLoading() { loadingInstance = ElLoading.service({ target: 'body', lock: true, text: '数据加载中,请稍后...', background: 'rgba(0, 0, 0, 0.7)', }) apiStore.addLoadingCount } function closeLoading() { apiStore.reduceLoadingCount const loadingCount = apiStore.loadingCount if (loadingCount { !noLoad && showLoading() axios.get(url, params) .then((response: AxiosResponse) => { sucCallback(resolve, response); !noLoad && closeLoading() }) .catch((response: AxiosResponse) => { !noLoad && closeLoading() failCallback(reject, response); }) }) } export function post(url: string, params?: any, noLoad?: boolean) { return new Promise((resolve, reject) => { !noLoad && showLoading() axios.post(url, params) .then((response: AxiosResponse) => { sucCallback(resolve, response); !noLoad && closeLoading() }) .catch((response: AxiosResponse) => { !noLoad && closeLoading() failCallback(reject, response); }) }) } vitest

配置文件见vite.config.ts

用于src/store/api.ts的单元测试

import { createApp } from 'vue' import { describe, expect, it, test } from 'vitest' import { useApiStore } from '../../store/api' import { createPinia } from 'pinia' import App from '../../App.vue' const pinia = createPinia() createApp(App).use(pinia) const apiStore = useApiStore(); describe('store/api.ts', () => { it('addLoadingCount', async () => { await apiStore.addLoadingCount(apiStore.$state) expect(apiStore.loadingCount).toBe(1) }) it('reduceLoadingCount', async () => { await apiStore.reduceLoadingCount(apiStore.$state) expect(apiStore.loadingCount).toBe(0) }) it('resetLoadingCount', async () => { await apiStore.addLoadingCount(apiStore.$state) await apiStore.resetLoadingCount(apiStore.$state) expect(apiStore.loadingCount).toBe(0) }) })

src/test/list.test.tsx

import { createApp } from 'vue' import { markRaw, nextTick, ref } from 'vue' import { mount } from '@vue/test-utils' import { describe, expect, it, test } from 'vitest' import List from '../../../views/List.vue' describe('StationList.vue', () => { const wrapper = mount(List) it('create', () => { expect(wrapper.html()).toContain('列表') }) })



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有