当前位置:   article > 正文

傻瓜式配置新项目vite+vue3+Element-plus+unocss+vue-router+axios+pinia+打包成zip_unocss vite

unocss vite

缘由:由于不经常创建新项目导致每次都忘,在这做个记录,再用的时候就直接翻翻,不用再查了

这里插一句,vite.config.ts 会被多次编辑,不用每次复制,结尾会贴一份完整的代码

路由守卫待续......

可能还有其他也待续......

写了一天写不动了......

1.先初始化项目

1.1 选择用vite构建,输入下面命令

npm create vite@latest

1.2 会问你是否继续,直接回车,默认为yes

1.3 输入项目名字

1.4 输入package.json中的名字,不能有大写

1.5 选择你所用的框架,用上下方向键选择,然后回车,我这里用了vue

1.6 选择用什么类型来开发,也是用上下方向键选择,然后回车,我这里用了TypeScript

1.7 然后就创建好了

1.8 然后跟着命令跑起来就行了,这是完整的截图

2.配置UI element-plus(点击这里查看文档)

2.1 先下载UI

npm install element-plus --save

2.2  然后配置按需导入

npm install -D unplugin-vue-components unplugin-auto-import
  1. // vite.config.ts
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. +import AutoImport from 'unplugin-auto-import/vite'
  5. +import Components from 'unplugin-vue-components/vite'
  6. +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  7. export default defineConfig({
  8. // ...
  9. plugins: [
  10. vue(),
  11. + AutoImport({
  12. + resolvers: [ElementPlusResolver()],
  13. + }),
  14. + Components({
  15. + resolvers: [ElementPlusResolver()],
  16. + }),
  17. ],
  18. })

2.3 自定义一个主题

2.3.1 先下载所需要的依赖
npm i @types/node scss -D
2.3.2 创建一个scss文件,路径为 src/assets/css/element.scss
  1. // styles/element/index.scss
  2. /* 只需要重写你需要的即可 */
  3. @forward 'element-plus/theme-chalk/src/common/var.scss' with (
  4. $colors: (
  5. 'primary': (
  6. 'base': #ff7e00,
  7. ),
  8. ),
  9. );
  10. // 如果只是按需导入,则可以忽略以下内容。
  11. // 如果你想导入所有样式:
  12. // @use "element-plus/theme-chalk/src/index.scss" as *;
 2.3.3 配置 vite.config.ts ,顺便把@也一起配置了
  1. + import { fileURLToPath, URL } from 'node:url'
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. import AutoImport from 'unplugin-auto-import/vite'
  5. import Components from 'unplugin-vue-components/vite'
  6. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  7. export default defineConfig({
  8. plugins: [
  9. vue(),
  10. AutoImport({
  11. resolvers: [ElementPlusResolver()],
  12. }),
  13. Components({
  14. resolvers: [ElementPlusResolver(
  15. + {importStyle: 'sass'}
  16. )],
  17. }),
  18. ],
  19. + resolve: {
  20. + alias: {
  21. + '@': fileURLToPath(new URL('./src', import.meta.url))
  22. + }
  23. + },
  24. + css: {
  25. + preprocessorOptions: {
  26. + scss: {
  27. + additionalData: `@use "@/assets/css/element.scss" as *;`,
  28. + }
  29. + }
  30. + }
  31. })

3.配置unocss(点击这里查看文档)

3.1 下载依赖

npm i unocss @unocss/preset-rem-to-px -D

 3.2 创建unocss.config.ts

  1. import { defineConfig, presetUno, presetAttributify } from 'unocss';
  2. // presetAttributify 属性化模式,属性冲突时,可以通过默认un-前缀来解决:<div m-2 rounded text-teal-400 >代替class</div>
  3. import presetRemToPx from '@unocss/preset-rem-to-px';
  4. // 此处我用了rem to px的预设,所以后面不加单位的数字的话会直接被转化为px(如果不用这个预设,就需要用m-100px之类的)
  5. export default defineConfig({
  6. presets: [presetUno(), presetAttributify(), presetRemToPx({ baseFontSize: 4 })],
  7. rules: [
  8. [/^fs-(\d+)$/, ([, num]) => ({ 'font-size': `${num}px` })],
  9. [/^lh-(\d+)$/, ([, num]) => ({ 'line-height': `${num}px` })]
  10. ],
  11. variants: [
  12. matcher => {
  13. if (!matcher.startsWith('hover:')) {
  14. return matcher;
  15. }
  16. return {
  17. matcher: matcher.slice(6),
  18. selector: s => `${s}:hover`
  19. };
  20. }
  21. ],
  22. shortcuts: {
  23. 'center': 'flex items-center justify-center'
  24. }
  25. });

3.3 配置 vite.config.ts 

  1. import { fileURLToPath, URL } from 'node:url'
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. import AutoImport from 'unplugin-auto-import/vite'
  5. import Components from 'unplugin-vue-components/vite'
  6. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  7. + import Unocss from 'unocss/vite'
  8. export default defineConfig({
  9. plugins: [
  10. vue(),
  11. + Unocss({
  12. + configFile: '@/unocss.config.ts'
  13. + }),
  14. AutoImport({
  15. resolvers: [ElementPlusResolver()],
  16. }),
  17. Components({
  18. resolvers: [ElementPlusResolver({
  19. importStyle: 'sass'
  20. })],
  21. }),
  22. ],
  23. resolve: {
  24. alias: {
  25. '@': fileURLToPath(new URL('./src', import.meta.url))
  26. }
  27. },
  28. css: {
  29. preprocessorOptions: {
  30. scss: {
  31. additionalData: `@use "@/assets/css/element.scss" as *;`,
  32. }
  33. }
  34. }
  35. })

3.4 配置main.ts 

  1. import { createApp } from 'vue'
  2. import './style.css'
  3. import App from './App.vue'
  4. + import 'uno.css'
  5. createApp(App).mount('#app')

4.配置vue-router

4.1 先下载依赖

npm install vue-router@4 -D

4.2 在src下创建 router/index.ts

  1. import { createRouter,createWebHashHistory } from "vue-router";
  2. import login from '@/views/login/login.vue'
  3. import home from '@/views/home/home.vue'
  4. let routes = [
  5. {
  6. path:'/',
  7. redirect:'/login'
  8. },
  9. {
  10. path: '/login',
  11. name: 'login',
  12. component: login
  13. },
  14. {
  15. path: '/home',
  16. name: 'home',
  17. component: home
  18. }
  19. ]
  20. const router = createRouter({
  21. history:createWebHashHistory(),
  22. routes
  23. })
  24. export default router

4.3 在 main.ts 中配置

  1. import { createApp } from 'vue'
  2. import './style.css'
  3. import App from './App.vue'
  4. import 'uno.css'
  5. + import router from '@/router/index.ts'
  6. - createApp(App).mount('#app')
  7. + createApp(App).use(router).mount('#app')

4.4 如果用了ts报错找不到类型啥的,在根目录下的 vite-env.d.ts 添加下面这个

  1. /// <reference types="vite/client" />
  2. + declare module "*ts"
  3. + declare module "*vue"

4.5 路由守卫 路由守卫先待续......

  1. const WhiteList = ['/login']; // 配置白名单
  2. router.beforeEach((to, from, next)=> {
  3. if (WhiteList.indexOf(to.fullPath) !== -1) { // 判断前往页面是都存在于白名单
  4. next()
  5. } else {
  6. if (localStorage.getItem('userInfo')) {// 判断用户是否d登录
  7. if (to.name) { // 判断是否存在路由的name名字,如果有则代表有路由表已经存在,name继续前往,反之,则不存在
  8. next()
  9. }
  10. else {// 当路由不存在,录取路由,动态添加路由表,
  11. let localRoutes: any = localStorage.getItem('routes');
  12. let recursionList = recursionParam(JSON.parse(localRoutes));
  13. for (let item of recursionList) {
  14. router.addRoute(item)
  15. }
  16. next({ ...to, replace: true })
  17. }
  18. } else {
  19. next('/login')
  20. }
  21. }
  22. });

5.配置交互axios

5.1先设置环境变量+代理

5.1.1 根目录下创建.env.production和.env.development
  1. # .env.development
  2. VITE_APP_MODE = "development"
  3. #base api
  4. VITE_APP_BASE_API = "/aaa/"
  5. # .env.production
  6. VITE_APP_MODE = "production"
  7. #base api
  8. VITE_APP_BASE_API = "https://xxx.xxx.com/"
5.1.2 vite.config.ts 中配置代理
  1. import { fileURLToPath, URL } from 'node:url'
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. import AutoImport from 'unplugin-auto-import/vite'
  5. import Components from 'unplugin-vue-components/vite'
  6. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  7. import Unocss from 'unocss/vite'
  8. export default defineConfig({
  9. plugins: [
  10. vue(),
  11. Unocss({
  12. configFile: '@/unocss.config.ts'
  13. }),
  14. AutoImport({
  15. resolvers: [ElementPlusResolver()],
  16. }),
  17. Components({
  18. resolvers: [ElementPlusResolver({
  19. importStyle: 'sass'
  20. })],
  21. }),
  22. ],
  23. resolve: {
  24. alias: {
  25. '@': fileURLToPath(new URL('./src', import.meta.url))
  26. }
  27. },
  28. css: {
  29. preprocessorOptions: {
  30. scss: {
  31. additionalData: `@use "@/assets/css/element.scss" as *;`,
  32. }
  33. }
  34. },
  35. + server: {
  36. + proxy: {
  37. + // 字符串代理
  38. + '/xxx': {
  39. + target: 'https://xxx.xxx.com/',
  40. + changeOrigin: true,
  41. + rewrite: (path) => path.replace(/^\/xxx/, '')
  42. + }
  43. + }
  44. + }
  45. })

5.2 配置axios

5.2.1 先下载axios
npm i axios qs -D
5.2.2 在src/utils下创建 api.js 编写 axios 的统一方法
  1. import axios from "axios"
  2. import qs from "qs"
  3. import { ElMessage } from 'element-plus'
  4. let key = "loading";
  5. const _LOGIN_URL = import.meta.env.VITE_APP_LOGIN_URL;
  6. const instance = axios.create({
  7. baseURL: import.meta.env.VITE_APP_BASE_API,
  8. timeout: 6000,
  9. });
  10. axios.interceptors.response.use((res) => {
  11. // return
  12. if (res.status != 200) {
  13. ElMessage.error("暂无网络,请稍后重试");
  14. ElMessage.destroy(key);
  15. return;
  16. }
  17. if (!res.data.code || res.config.headers.status == 3) {
  18. ElMessage.destroy(key);
  19. return res.data;
  20. }
  21. if (res.data.code == 301) {
  22. ElMessage.error("身份已过期,请重新登录");
  23. ElMessage.destroy(key);
  24. let expireTime = setTimeout(() => {
  25. window.location.href = _LOGIN_URL;
  26. clearTimeout(expireTime);
  27. }, 3000);
  28. return;
  29. }
  30. if (res.data.code == 313) {
  31. ElMessage.error("未登录,请登录");
  32. ElMessage.destroy(key);
  33. let notLoginTime = setTimeout(() => {
  34. window.location.href = _LOGIN_URL;
  35. clearTimeout(notLoginTime);
  36. }, 3000);
  37. return;
  38. }
  39. ElMessage.destroy(key);
  40. return res.data;
  41. },
  42. (error) => {
  43. return error;
  44. }
  45. );
  46. instance.interceptors.request.use((config) => {
  47. console.log(config);
  48. return config;
  49. }, (error) => {
  50. // 对请求错误做些什么
  51. return Promise.reject(error);
  52. }
  53. );
  54. const requestApi = (method, url, params, status, headers) => {
  55. // status 0: 都显示 1: 不显示loading 2: 不显示报错 3: 都不显示
  56. if (status != 1 || status != 3) {
  57. message.loading({ content: "加载中", key: key, duration: 0 });
  58. }
  59. headers.status = status;
  60. return new Promise((resolve, reject) => {
  61. instance({
  62. method: method,
  63. headers: headers,
  64. url,
  65. params: method == "GET" && params,
  66. data: method == "POST" && qs.stringify(params)
  67. }).then(res => {
  68. resolve(res.data);
  69. }).catch(err => {
  70. reject(err);
  71. });
  72. })
  73. }
  74. const login = (params) => requestApi("POST", "/login", params, 0, { "Content-Type": "application/x-www-form-urlencoded" });
  75. export {
  76. login
  77. }

6. 配置pinia

6.1 先下载所需的依赖

  pinia-plugin-persistedstate是为了将store存在本地存储中,这样刷新页面关键信息也不会丢失

npm install pinia pinia-plugin-persistedstate -D

6.2 然后在 main.ts 中配置 

  1. import { createApp } from 'vue'
  2. import './style.css'
  3. import App from './App.vue'
  4. import 'uno.css'
  5. import router from '@/router/index.ts'
  6. + import { createPinia } from "pinia";
  7. + import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
  8. - createApp(App).use(router).mount('#app')
  9. + const app = createApp(App);
  10. + const store = createPinia();
  11. + store.use(piniaPluginPersistedstate);
  12. + for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  13. + app.component(key, component)
  14. + }
  15. + app.use(router).use(store).mount("#app");

6.3 如何配置 

  简单举个例子,创建文件,路径为 src/store/user.ts 

  1. import { defineStore } from "pinia"
  2. let _LOGIN_URL = import.meta.env.VITE_APP_LOGIN_URL; // 从环境变量中拿到当前应该跳转到哪个地址
  3. export const useUserStore = defineStore('user', {
  4. state: () => {
  5. return {
  6. token: '', // 用户token
  7. userInfo: {}, // 用户信息
  8. }
  9. },
  10. persist: {
  11. storage: sessionStorage, // 这里设置存储方式,也可以是 localStorage
  12. paths: ['userInfo', 'token'], // 要存储的哪个字段
  13. },
  14. actions: {
  15. setToken(token: string) {
  16. this.token = token; // 修改
  17. },
  18. setUserInfo(userInfo: any) {
  19. this.userInfo = userInfo;
  20. },
  21. logout() {
  22. window.sessionStorage.clear();
  23. window.location.href = _LOGIN_URL;
  24. // 调用方法,这里只能把存储里的删掉,pinia本身还需要多加一步$reset()来清除,这个后面有体现
  25. }
  26. }
  27. })

6.4 如何调用操作 

在vue文件中,举个例子,可以结合自己需求去完成

  1. <script setup lang="ts">
  2. import { useUserStore } from "@/store/user";
  3. const userStore: any = useUserStore();
  4. onMounted(() => {
  5. if (!userStore.token) { // 这里直接就能使用
  6. // 没有登录信息
  7. router.push({
  8. name: "login",
  9. });
  10. return;
  11. }
  12. // 这里举个例子怎么使用
  13. // 1. 调用事件去修改
  14. let token = "xajxbnajsbxjasbxhsbxhsabxjhbsajhbxa";
  15. userStore.setToken(token);
  16. // 2. 本身自带的方法去修改
  17. userStore.$patch((state) => {
  18. state.token = token;
  19. })
  20. // 3.直接修改不推荐,能不用就不用吧
  21. userStore.token = token;
  22. })
  23. const logout = () => {
  24. // 退出登录
  25. userStore.$reset(); // 清空本身store中所有数据
  26. userStore.logout(); // 调用方法
  27. };
  28. </script>

7. 配置打包zip 

7.1 先下载依赖

pnpm install vite-plugin-zip-pack -D

7.2 配置vite.config.ts

  1. import { fileURLToPath, URL } from 'node:url'
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. import AutoImport from 'unplugin-auto-import/vite'
  5. import Components from 'unplugin-vue-components/vite'
  6. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  7. import Unocss from 'unocss/vite'
  8. + import zipPack from "vite-plugin-zip-pack";
  9. export default defineConfig({
  10. plugins: [
  11. vue(),
  12. Unocss({
  13. configFile: '@/unocss.config.ts'
  14. }),
  15. AutoImport({
  16. resolvers: [ElementPlusResolver()],
  17. }),
  18. Components({
  19. resolvers: [ElementPlusResolver({
  20. importStyle: 'sass'
  21. })],
  22. }),
  23. + zipPack({
  24. + inDir: 'xxx', // 输入的文件夹,即要打包的文件夹
  25. + outDir: './', // 打包好的zip文件放置的位置
  26. + outFileName: 'xxx.zip', // 打包好的文件名
  27. + pathPrefix: '' // 可选,文件路径前缀
  28. + }),
  29. ],
  30. resolve: {
  31. alias: {
  32. '@': fileURLToPath(new URL('./src', import.meta.url))
  33. }
  34. },
  35. css: {
  36. preprocessorOptions: {
  37. scss: {
  38. additionalData: `@use "@/assets/css/element.scss" as *;`,
  39. }
  40. }
  41. },
  42. server: {
  43. proxy: {
  44. // 字符串代理
  45. '/xxx': {
  46. target: 'https://xxx.xxx.com/',
  47. changeOrigin: true,
  48. rewrite: (path) => path.replace(/^\/xxx/, '')
  49. }
  50. }
  51. }
  52. })

8. 结尾

8.1 vite.config.ts

  1. import { fileURLToPath, URL } from 'node:url'
  2. import { defineConfig } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. import AutoImport from 'unplugin-auto-import/vite'
  5. import Components from 'unplugin-vue-components/vite'
  6. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  7. import Unocss from 'unocss/vite'
  8. import zipPack from "vite-plugin-zip-pack"
  9. export default defineConfig({
  10. plugins: [
  11. vue(),
  12. Unocss({
  13. configFile: '@/unocss.config.ts'
  14. }),
  15. AutoImport({
  16. resolvers: [ElementPlusResolver()],
  17. }),
  18. Components({
  19. resolvers: [ElementPlusResolver({
  20. importStyle: 'sass'
  21. })],
  22. }),
  23. zipPack({
  24. inDir: 'xxx', // 输入的文件夹,即要打包的文件夹
  25. outDir: './', // 打包好的zip文件放置的文件夹
  26. outFileName: 'xxx.zip', // 打包好的文件名
  27. pathPrefix: '' // 可选,文件路径前缀
  28. })
  29. ],
  30. resolve: {
  31. alias: {
  32. '@': fileURLToPath(new URL('./src', import.meta.url))
  33. }
  34. },
  35. css: {
  36. preprocessorOptions: {
  37. scss: {
  38. additionalData: `@use "@/assets/css/element.scss" as *;`,
  39. }
  40. }
  41. },
  42. server: {
  43. proxy: {
  44. // 字符串代理
  45. '/xxx': {
  46. target: 'https://xxx.xxx.com/',
  47. changeOrigin: true,
  48. rewrite: (path) => path.replace(/^\/xxx/, '')
  49. },
  50. }
  51. }
  52. })

8.2 main.ts

  1. import { createApp } from 'vue'
  2. import './style.css'
  3. import App from './App.vue'
  4. import 'uno.css'
  5. import router from '@/router/index.ts'
  6. import { createPinia } from "pinia";
  7. import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
  8. createApp(App).use(router).mount('#app')
  9. const app = createApp(App);
  10. const store = createPinia();
  11. store.use(piniaPluginPersistedstate);
  12. for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  13. app.component(key, component)
  14. }
  15. app.use(router).use(store).mount("#app");

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

闽ICP备14008679号