您现在的位置是:首页 >技术杂谈 >vite4 + vue3 + pinia + axios + vue-router + elementPlus网站首页技术杂谈

vite4 + vue3 + pinia + axios + vue-router + elementPlus

微笑边缘的金元宝 2023-05-16 04:00:02
简介vite4 + vue3 + pinia + axios + vue-router + elementPlus

很全面很长的搭建过程,一定要看完!!!

本机环境问题

npm create vite@latest

创建项目后

npm i
npm run dev

报错: ‘vite’ 不是内部或外部命令,也不是可运行的程序
或批处理文件。

node_modules 有但是就是找不到
使用pnpm i 重新加载依赖就可以了
关键是其他电脑上没有这个问题…(可能是我本机配置有问题)
最最厉害的就是同一台电脑,在另一个文件夹下用npm就可以

正式开始

项目创建完就有vite和vue了

"vite": "^4.2.0"
"vue": "^3.2.47"

需要安装的插件表格(希望需要安装的插件越来越少!!!)

插件名称备注
pinia等同与 vuex
axiosapi请求库
vue-router路由
elementPlusUI框架
unplugin-auto-import为 Vite、Webpack、Rollup 和 esbuild 按需自动导入 API。支持 TypeScript。
unplugin-vue-componentsVue 的按需组件自动导入。
vite-plugin-compression压缩大文件
rollup-plugin-visualizer这是一个依赖分析插件,它提供了多种模式的依赖分析,包括直观的视图分析,sunburst(循环层次图,像光谱)、treemap(矩形层次图,看起来比较直观,也是默认参数)、network(网格图,查看包含关系)、raw-data(原数据模式,json格式), list(列表模式)
eslinteslint针对的是javascript,他是一个检测工具,包含js语法以及少部分格式问题,在eslint看来,语法对了就能;保证代码正常允许,格式问题属于其次;
prettierprettier属于格式化工具,它看不惯格式不统一,所以它就把eslint没干好的事接着干,另外,prettier支持,包含js在内的多种语言
@vitejs/plugin-legacy为打包后的文件提供传统浏览器兼容性支持。
vite-plugin-vue-setup-extend在script标签中添加name属性具体看:https://blog.csdn.net/m0_50074446/article/details/125300541
unplugin-icons自动按需加载在图标,包括element plus 但是不仅仅时 element plus;使用教程请点击具体包含图标内容查看iconify官网请点击unplugin-icons github请点击

安装 pinia

pnpm install --save pinia
"dependencies": {
    "pinia": "^2.0.34",
    "vue": "^3.2.47"
  },

创建文件夹:srcstoresindex.js
主要是创建一个实例

// https://pinia.vuejs.org/
import { createPinia } from 'pinia';

// 创建
const pinia = createPinia();

// 导出
export default pinia;

挂载vue

import { createApp } from 'vue';
import pinia from './stores/index';
const app = createApp(App);
app.use(pinia).mount('#app');

使用时:
创建:srcstoresuserindex.js

import { defineStore } from "pinia";

export const user = defineStore('user', {
  state: () => ({
    user: {
      total: 0,
      page: 1,
      limit: 10,
    }
  }),
  actions: {
    getList() {
      //...
    },
  }
})

在组件中使用

<script setup>
import {user} from '/@/stores/user/index';
const store = user();
// ...
store.getList({...}); // 直接调用是不是很方便
// ...
store.user.page; // 直接获取
</script>

更多详细使用请点击此处

安装axios

pnpm i axios
// 或者
npm i axios

创建文件: srcutils equest.js

import axios from 'axios';
// 配置新建一个 axios 实例
const service = axios.create({
	baseURL: import.meta.env.VITE_API_URL, // 环境变量
	timeout: 50000,
	headers: { 'Content-Type': 'application/json' },
});
// 添加请求拦截器
service.interceptors.request.use(
	(config) => {
		// 在发送请求之前做些什么
		return config;
	},
	(error) => {
		// 对请求错误做些什么
		return Promise.reject(error);
	}
);

// 添加响应拦截器
service.interceptors.response.use(
	(response) => {
		// 对响应数据做点什么
		const res = response.data;
		const {status, data, message} = response || {};
		if (status !== 200) {
			const {message: messageErr} = service.interceptors.response.data || {};
			return Promise.reject(messageErr);
		} else {
			return {status, data};
		}
	},
	(error) => {
		const {data, status} = error.response || {};
		// 对响应错误做点什么 ...
		return Promise.reject(messageErr);
	}
);
// 导出 axios 实例
export default service;

使用时:
创建

import request from "../../utils/request";

export function userlist(params) {
  return request({
    url: `/userlist`,
    method: "GET",
    params,
  });
}

export function addUser(params) {
  return request({
    url: `/addUser`,
    method: "POST",
    data: {
      ...params
    }
  });
}

在组件中使用

<script setup>
import {deleteRoleApi} from '/@/api/...';
deleteRoleApi(id).then(res => {})
</script>

安装vue-router

pnpm install vue-router --save
//"vue-router": "^4.1.6"

创建文件:src outerindex.js

import { createRouter, createWebHashHistory } from 'vue-router';
const staticRoutes = [
	{
		path: '/login',
		name: 'login',
		component: () => import('/@/views/login/index.vue'),
		meta: {
			title: '登录',
		},
	},
];
/**
 * 创建一个可以被 Vue 应用程序使用的路由实例
 * @method createRouter(options: RouterOptions): Router
 * @link 参考:https://next.router.vuejs.org/zh/api/#createrouter
 */
export const router = createRouter({
	history: createWebHashHistory(),
	routes: staticRoutes,
});
// 路由加载前
router.beforeEach(async (to, from, next) => {
	next();
});
// 路由加载后
router.afterEach(() => {});

// 导出路由
export default router;

动态添加路由

import { router } from '/@/router/index';
setTimeout((route) => { // 模拟接口请求
	router.addRoute(route);
},5000)

挂载到vue

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import pinia from './stores/index'

const app = createApp(App)
app.use(pinia).use(router).mount('#app')

安装 按需加载 element plus

pnpm install element-plus

安装相关按需加载的插件

npm install -D unplugin-vue-components unplugin-auto-import unplugin-icons

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'

const pathResolve = (dir) => {
	return resolve(__dirname, '.', dir);
};

const alias = {
	'/@': pathResolve('./src/'),
};

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      imports: ['vue', 'vue-router'], // 自动引入相关api
      resolvers: [
        ElementPlusResolver(),
        IconsResolver({
          prefix: 'icon',
          // enabledCollections: ['ep'],
          // 标识自定义图标集
          customCollections: ['ci']
        })
      ],
   }),
   Components({
      resolvers: [
        ElementPlusResolver(),
        IconsResolver({
          prefix: 'icon',
          // enabledCollections: ['ep'],
          // 标识自定义图标集
          customCollections: ['ci']
        })
      ],
   }),
   Icons({
    compiler: 'vue3',
    autoInstall: true,
    // 自定义配置
    customCollections: { 
      ci: FileSystemIconLoader('./src/assets/svg', svg => svg.replace(/^<svg /, '<svg fill="currentColor" '))
    }
  }),
  ],
  resolve: { alias },
})

使用方式,直接用不需要import

<script setup>

import IconBaseline5g from '~icons/ep/edit'

</script>

<template>
  

<!-- 使用component 需要先引用 -->
  <el-icon :size="20">
    <component :is="IconBaseline5g" />
  </el-icon>
  <!--  直接使用,不需要引用 -->
  <!-- icon是头部(上面vite.config.js 配置的prefix: 'icon'-->
  <!-- ep是element plus图标库的简称 edit是图标的名字 -->
  <el-icon :size="20">
    <iconEpEdit />
  </el-icon>
  <!--  使用本地自定义的svg -->
  <!-- icon是头部(上面vite.config.js 配置的prefix: 'icon'-->
  <!-- Ci是自定义图标的集合(上面vite.config.js 配置的customCollections: { 
      ci: FileSystemIconLoader...) vue是自定义目录下的svg文件的名称 -->
  <el-icon :size="20">
    <iconCiVue />
  </el-icon>
</template>

静态资源动态引用:图片

vite官方推荐
使用require的可以用上面的方法替换

@vitejs/plugin-legacy

安装
必须安装 Terser,因为插件遗留版使用 Terser 进行缩小。

pnpm i -D @vitejs/plugin-legacy terser
// vite.config.js
import legacy from '@vitejs/plugin-legacy'

export default {
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11'],
    }),
  ],
}

vite-plugin-vue-setup-extend 在script标签中添加name属

安装

pnpm i vite-plugin-vue-setup-extend -D
import VueSetupExtend from 'vite-plugin-vue-setup-extend'

export default defineConfig({
  plugins: [
    VueSetupExtend()
  ]
})

vite-plugin-compression 压缩大文件

安装

pnpm i -D vite-plugin-compression
import viteCompression from "vite-plugin-compression";
plugins: [
			viteCompression({
				verbose: true,
				disable: false,
				deleteOriginFile: false,
				// 文件大于 100Kb 开启压缩 
				threshold: 100000,
				algorithm: "gzip",
				ext: "gz",
			}),
		],

压缩文件需要搭配nginx 配置,详情请点击

rollup-plugin-visualizer 这是一个依赖分析插件

参考链接:https://blog.csdn.net/g18204746769/article/details/127431733
安装

pnpm install vite-plugin-cdn-import --save-dev
import { visualizer } from 'rollup-plugin-visualizer';
plugins: [
	visualizer()
]

vite.config.js全部的配置

想了解配置想请点击

import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import legacy from '@vitejs/plugin-legacy'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
import viteCompression from 'vite-plugin-compression'

const pathResolve = (dir) => {
  return resolve(__dirname, '.', dir)
}

const alias = {
  '/@': pathResolve('./src/'),
}

// https://vitejs.dev/config/
export default defineConfig((mode) => {
  // mode 拿的是 process.argv的参数。例如:package.json script 中 "vite build --mode prd" 的 --mode 后面的值
  // 想在vite.config.ts中使用环境变量,要用vite提供的loadEnv(mode, process.cwd())
  const env = loadEnv(mode.mode, process.cwd())
  return {
    plugins: [
      legacy({
        targets: ['defaults', 'not IE 11'],
      }),
      vue(),
      viteCompression({
        verbose: true,
        disable: false,
        deleteOriginFile: false,
        // 文件大于 100Kb 开启压缩
        threshold: 100000,
        algorithm: 'gzip',
        ext: 'gz',
      }),
      vueSetupExtend(),
      AutoImport({
        imports: ['vue', 'vue-router'], // 自动引入相关api
        resolvers: [
          ElementPlusResolver(),
          IconsResolver({
            prefix: 'Deep',
            // enabledCollections: ['ep'],
            // 标识自定义图标集
            customCollections: ['ci'],
          }),
        ],
      }),
      Components({
        resolvers: [
          ElementPlusResolver(),
          IconsResolver({
            prefix: 'Deep',
            // enabledCollections: ['ep'],
            // 标识自定义图标集
            customCollections: ['ci'],
          }),
        ],
      }),
      Icons({
        compiler: 'vue3',
        autoInstall: true,
        customCollections: {
          ci: FileSystemIconLoader('./src/assets/svg', (svg) =>
            svg.replace(/^<svg /, '<svg fill="currentColor" '),
          ),
        },
      }),
    ],
    resolve: { alias },
    root: process.cwd(),
    // 当前启动的命令 command
    base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH,
    server: {
      host: '0.0.0.0',
      port: env.VITE_PORT,
      open: false,
      proxy: {
        '/api': {
          target: 'https://gitee.com',
          ws: true,
          changeOrigin: true,
          rewrite: (path) => path.replace(/^/gitee/, ''),
        },
      },
    },
    build: {
      outDir: 'dist',
      chunkSizeWarningLimit: 1500,
      rollupOptions: {
        output: {
          entryFileNames: `assets/[name].${new Date().getTime()}.js`,
          chunkFileNames: `assets/[name].${new Date().getTime()}.js`,
          assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`,
          compact: true,
          // manualChunks: {
          // 	vue: ['vue', 'vue-router', 'pinia'],
          // 	echarts: ['echarts'],
          // antvG6: ['@antv/g6'],
          // elementPlus: ['element-plus'],
          // },
          manualChunks(id) {
            // if (id.includes("style.css")) {
            // 	// 需要单独分割那些资源 就写判断逻辑就行
            // 	return 'src/style.css';
            // }
            // if (id.includes("HelloWorld.vue")) {
            // 	// 单独分割hello world.vue文件
            // 	return 'src/components/HelloWorld.vue';
            // }
            // // 最小化拆分包
            if (id.includes('node_modules')) {
              return id
                .toString()
                .split('node_modules/')[1]
                .split('/')[0]
                .toString()
            }
          },
        },
      },
      minify: 'terser',
      terserOptions: {
        compress: {
          drop_console: mode.mode === 'production',
          drop_debugger: mode.mode === 'production',
        },
      },
      sourcemap: mode.mode !== 'production',
    },
    css: {
      devSourcemap: true,
      preprocessorOptions: { css: { charset: false } },
    },
  }
})

安装eslint && prettier

根据个人需求,我参考的这几个链接:
http://52code.net/a/bAwoc9jJ7M
https://segmentfault.com/a/1190000041954694?utm_source=sf-similar-article
https://zhuanlan.zhihu.com/p/619030608
https://juejin.cn/post/7077346415424307214
https://blog.csdn.net/lijiahui_/article/details/128134797
https://blog.csdn.net/weixin_43459866/article/details/124249172

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。