• vue3项目学习二:搭建项目架构



    记录一下vite+vue3+ts项目搭建过程,参考大佬 Vue3.3 + Vite4.3 + Element-Plus + TypeScript 从0到1搭建企业级后台管理系统(前后端开源)的文章来搭建。

    一、 环境及软件准备

    类型名称
    开发工具vscode
    运行环境nodejs 版本16+
    vscode插件必需:TypeScript Vue Plugin (Volar)Vue Language Features (Volar) 非必需:Chinese (Simplified) (简体中文) Language Pack for Visual Studio CodeAuto Close TagAuto Rename TagESLintPath IntellisensePrettier - Code formatterSvg Preview

    二、创建vite项目

    地址:vite

    npm create vite@latest
    
    • 1

    在这里插入图片描述
    启动:

     npm install
     npm run dev
    
    • 1
    • 2

    三、配置src 路径别名

    使用 @ 代替 src

    vite.config.ts添加

    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import path from 'path'
    
    const pathSrc = path.resolve(__dirname,"src")
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [vue()],
      resolve:{
        alias:{
          "@" : pathSrc
        }
      }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    找不到模块“path”或其相应的类型声明。ts(2307)解决:

    安装 Node 的 TypeScript 类型描述文件

    npm install @types/node --save-dev
    
    • 1

    找不到模块“@/components/HelloWorld.vue”或其相应的类型声明。ts(2307)解决:

    因为 typescript 特殊的 import 方式 , 需要在tsconfig.json中配置允许默认导入的方式,还有路径别名的配置

      "compilerOptions": {
        "baseUrl": "./", // 解析非相对模块的基地址,默认是当前目录
        "paths": { //路径映射,相对于baseUrl
          "@/*": ["src/*"] 
        },
        "allowSyntheticDefaultImports": true ,// 允许默认导入
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用

    import HelloWorld from './components/HelloWorld.vue'
    
    import HelloWorld from '@/components/HelloWorld.vue';
    
    
    • 1
    • 2
    • 3
    • 4

    四、自动导入

    element plus推荐使用按需导入的方法,推荐使用unplugin-vue-componentsunplugin-auto-import这两款插件,这两款插件不仅可以使element+按需导入,还可以自动导入vue3ref,computed

    安装:

    npm install -D unplugin-auto-import unplugin-vue-components 
    
    • 1

    vite.config.ts - 自动导入配置

    先创建好 /src/types 目录用于存放自动导入函数和组件的TS类型声明文件,再进行自动导入配置

    import path from 'path'
    import AutoImport from "unplugin-auto-import/vite";
    import Components from "unplugin-vue-components/vite";
    
      plugins: [
        vue(),
        AutoImport({
          // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
          imports: ["vue"],
          eslintrc: {
            enabled: true, // 是否自动生成 eslint 规则,建议生成之后设置 false 
            filepath: "./.eslintrc-auto-import.json", // 指定自动导入函数 eslint 规则的文件
          },
          dts: path.resolve(pathSrc, "types", "auto-imports.d.ts"), // 指定自动导入函数TS类型声明文件路径
        }),
        Components({
          dts: path.resolve(pathSrc, "types", "components.d.ts"), // 指定自动导入组件TS类型声明文件路径
        }),
      ],
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    五、配置element+

    地址:element plus

    安装:

    npm install element-plus
    
    • 1

    安装自动导入 Icon 依赖

    npm i -D unplugin-icons
    
    • 1

    配置vite.config.ts文件

    // vite.config.ts
    import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
    import Icons from "unplugin-icons/vite";
    import IconsResolver from "unplugin-icons/resolver";
    
    export default ({ mode }: ConfigEnv): UserConfig => {
    
      return {
        plugins: [
          // ...
          AutoImport({
            // ...  
            resolvers: [
              // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)
              ElementPlusResolver(),
              // 自动导入图标组件
              IconsResolver({}),
            ]
            vueTemplate: true, // 是否在 vue 模板中自动导入
            dts: path.resolve(pathSrc, 'types', 'auto-imports.d.ts') // 自动导入组件类型声明文件位置,默认根目录
              
          }),
          Components({ 
            resolvers: [
              // 自动导入 Element Plus 组件
              ElementPlusResolver(),
              // 自动注册图标组件
              IconsResolver({
                enabledCollections: ["ep"] // element-plus图标库,其他图标库 https://icon-sets.iconify.design/
              }),
            ],
            dts: path.resolve(pathSrc, "types", "components.d.ts"), //  自动导入组件类型声明文件位置,默认根目录
          }),
          Icons({
            // 自动安装图标库
            autoInstall: true,
          }),
        ],
      };
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    使用el-icon

    <i-ep-SuccessFilled />
    <i-ep-InfoFilled />
    <i-ep-WarningFilled />
    
    • 1
    • 2
    • 3

    六、整合 SVG 图标

    通过 vite-plugin-svg-icons 插件整合 Iconfont 第三方图标库实现本地图标

    安装依赖:

    npm i vite-plugin-svg-icons -D
    npm i fast-glob -D 
    
    • 1
    • 2

    创建src/assets/icons文件夹存放svg文件,并把svg文件存入文件夹中
    在这里插入图片描述
    main.ts中注册svg

    import 'virtual:svg-icons-register';
    
    • 1

    vite.config.ts 配置插件

    import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
    
    export default defineConfig({
      plugins: [
    	createSvgIconsPlugin({
          // 指定需要缓存的图标文件夹
          iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
          // 指定symbolId格式
          symbolId: 'icon-[dir]-[name]',
        })
      ]
    })
    			
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    使用:

    <svg-icon icon-class="block"/>
    
    • 1

    七、整合SCSS

    安装:

    npm i -D sass 
    
    • 1

    创建全局变量文件src/styles/variables.scss

    $navbarHeight: 50px;
    
    • 1

    vite.config.ts导入全局配置文件

    export default defineConfig({
      css: {
        // CSS 预处理器
        preprocessorOptions: {
          // 定义全局 SCSS 变量
          scss: {
            javascriptEnabled: true,
            additionalData: `
              @use "@/styles/variables.scss" as *;
            `,
          },
        },
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在scss中可以直接使用:

    bgColor:$bg-color
    
    • 1

    但是在ts中需要创建一个以 .module.scss 结尾的文件

    // src/styles/variables.module.scss
    
    // 导出 variables.scss 文件的变量
    :export{
        bgColor:$bg-color
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在ts中使用:

    <script setup lang="ts">
      import variables from "@/styles/variables.module.scss";
      console.log(variables.bgColor)  
    </script>
    
    • 1
    • 2
    • 3
    • 4

    八、整合 UnoCSS

    安装UnoCSS

    npm install -D unocss
    
    • 1

    vite.config.ts 配置

    // vite.config.ts
    import UnoCSS from 'unocss/vite'
    
    export default {
      plugins: [
        UnoCSS({ /* options */ }),
      ],
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    main.ts 引入 uno.css

    // src/main.ts
    import 'uno.css'
    
    
    • 1
    • 2
    • 3

    VSCode 安装 UnoCSS 插件
    在这里插入图片描述

    九、整合pinia

    安装pinia

    npm install pinia
    
    • 1

    main.ts引入:

    // src/main.ts
    import { createPinia } from "pinia";
    import App from "./App.vue";
    
    createApp(App).use(createPinia()).mount("#app");
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建src/store/xxx.ts

    export const useStore = defineStore('main', {
      state: () => ({
        counter: 0,
      }),
      getters: {
        doubleCount: (state) => state.counter * 2,
      },
      actions: {
        increment() {
          this.counter++
        },
        randomizeCounter() {
          this.counter = Math.round(100 * Math.random())
        },
      },
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    使用:

    import { useStore } from "@/store/counter";
    const counterStore = useStore ();
    counterStore.increment()
    
    • 1
    • 2
    • 3

    十、配置环境变量

    项目根目录新建 .env.development.env.production
    .env.development配置:

    # 变量必须以 VITE_ 为前缀才能暴露给外部读取
    VITE_APP_TITLE = 'vue3-element-admin'
    VITE_APP_PORT = 3000
    VITE_APP_BASE_API = '/dev-api'
    
    • 1
    • 2
    • 3
    • 4

    .env.production配置

    VITE_APP_TITLE = 'vue3-element-admin'
    VITE_APP_PORT = 3000
    VITE_APP_BASE_API = '/prod-api'
    
    • 1
    • 2
    • 3

    新建 src/types/env.d.ts文件存放环境变量TS类型声明

    // src/types/env.d.ts
    interface ImportMetaEnv {
      /**
       * 应用标题
       */
      VITE_APP_TITLE: string;
      /**
       * 应用端口
       */
      VITE_APP_PORT: number;
      /**
       * API基础路径(反向代理)
       */
      VITE_APP_BASE_API: string;
    }
    
    interface ImportMeta {
      readonly env: ImportMetaEnv;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    引入:

    import.meta.env.xxx
    
    • 1

    十一、反向代理

    vite.config.ts 配置代理

    import vue from '@vitejs/plugin-vue'
    import { UserConfig, ConfigEnv, loadEnv, defineConfig } from "vite";
    import path from 'path'
    import AutoImport from "unplugin-auto-import/vite";
    import Components from "unplugin-vue-components/vite";
    import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
    import Icons from "unplugin-icons/vite";
    import IconsResolver from "unplugin-icons/resolver";
    import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
    import UnoCSS from 'unocss/vite'
    const pathSrc = path.resolve(__dirname,"src")
    
    // https://vitejs.dev/config/
    export default defineConfig(({mode}) => {
      const env = loadEnv(mode, process.cwd());
      return {
        server: {
          // 允许IP访问
          host: "0.0.0.0",
          // 应用端口 (默认:3000)
          port: Number(env.VITE_APP_PORT),
          // 运行是否自动打开浏览器
          open: true,
          proxy: {
            /**
             * 反向代理解决跨域配置
             * http://localhost:3000/dev-api/users (F12可见请求路径) => http://localhost:8989/users (实际请求后端 API 路径)
             *
             * env.VITE_APP_BASE_API: /dev-api
             * env.VITE_APP_TARGET_URL: http://localhost:8989
             * env.VITE_APP_TARGET_BASE_API: ""
             */
            [env.VITE_APP_BASE_API]: {
              changeOrigin: true,
              target: env.VITE_APP_TARGET_URL,
              rewrite: (path) =>
                path.replace(
                  new RegExp("^" + env.VITE_APP_BASE_API),
                  env.VITE_APP_TARGET_BASE_API
                ),
            },
          },
        },
        plugins: [
          vue(),
          UnoCSS({ /* options */ }),
          AutoImport({
            // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
            imports: ["vue"],
            resolvers: [
              // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)
              ElementPlusResolver(),
              // 自动导入图标组件
              IconsResolver({}),
            ],
            vueTemplate: true, // 是否在 vue 模板中自动导入
            eslintrc: {
              enabled: true, // 是否自动生成 eslint 规则,建议生成之后设置 false 
              filepath: "./.eslintrc-auto-import.json", // 指定自动导入函数 eslint 规则的文件
            },
            dts: path.resolve(pathSrc, "types", "auto-imports.d.ts"), // 指定自动导入函数TS类型声明文件路径
          }),
          Components({
            resolvers: [
              // 自动导入 Element Plus 组件
              ElementPlusResolver(),
              // 自动注册图标组件
              IconsResolver({
                enabledCollections: ["ep"] // element-plus图标库,其他图标库 https://icon-sets.iconify.design/
              }),
            ],
            dts: path.resolve(pathSrc, "types", "components.d.ts"), // 指定自动导入组件TS类型声明文件路径
          }),
          Icons({
            // 自动安装图标库
            autoInstall: true,
          }),
          createSvgIconsPlugin({
            // 指定需要缓存的图标文件夹
            iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
            // 指定symbolId格式
            symbolId: 'icon-[dir]-[name]',
          })
        ],
        resolve:{
          alias:{
            "@" : pathSrc
          }
        },
        css: {
          // CSS 预处理器
          preprocessorOptions: {
            // 定义全局 SCSS 变量
            scss: {
              javascriptEnabled: true,
              additionalData: `
                @use "@/styles/variables.scss" as *;
              `,
            },
          },
        },
      }
    
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105

    十二、移动端适配

    使用Vue进行移动端页面的开发,需要对不同机型的宽高进行适配。最常用的方法是使用amfe-flexable和postcss-pxtorem这两个插件来帮助进行适配。

    安装:

    npm install postcss-pxtorem --save-dev
    npm install amfe-flexible --save-dev
    
    • 1
    • 2

    main.ts中引入

    import 'amfe-flexible'
    
    • 1

    在vite.config.js中配置postcss-pxtorem

    import postCssPxToRem from 'postcss-pxtorem'
    
    export default defineConfig({
      css:{
        postcss:{
          plugins:[
            postCssPxToRem({
              rootValue:37.5,
              propList:['*'],
            })
          ]
        }
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    迅为IMX6Q开发板QT系统移植tinyplay
    到底什么是“星闪”?
    【华为OD机试真题 python】英文输入法 【2022 Q4 | 100分】
    11.30排序
    HBASE集群主节点迁移割接手动操作步骤
    halcon算子3、emphasize
    【工作笔记】缓存里的几种模式
    leetcode 刷题 log day 42
    SpringOAuth2授权流程分析
    c++ SFML 获取ftp某个目录下所有的文件或者文件夹
  • 原文地址:https://blog.csdn.net/weixin_42645490/article/details/132985674