用 vite 构建 vue3 + TS 项目实战

4 篇文章 0 订阅
2 篇文章 1 订阅

目录

1、项目初始化

 2、eslint 基础配置

3、配置 git commit hook 

4、在开发和构建中进行代码规范校验

5、GitCommit规范 

6、 Vite中的TS环境说明 

7、Vue3 中 Ts 支持

8、Vue3中的script-setup语法 

9、script-setup中的编译宏 

10、配置转换JSX和TSX 

11、初始化 Vue Router 

12、初始化 Vuex

13、配置模块路径别名

14、CSS 样式管理 

15、和服务端交互

16、多环境 baseURL

17、跨域问题

18、初始化 Element Plus

18、项目地址


1、项目初始化

  • npm install create-vite@2.9.0 -g // 全局安装 create-vite
  • npm init @vitejs/app shop-admin // 初始化项目(shop-admin 项目名)
  • cd shop-admin
  • npm install
  • npm run dev

 2、eslint 基础配置

  • npm install eslint --save-dev
  • npm install @eslint/create-config@latest -D
  • npm  init @eslint/config

  • 修改 .eslintrc.js的配置,修改为 'plugin:vue/vue3-strongly-recommended'(适用于 vue3版本的eslint)

  •  在 npm scripts 中添加验证脚本:"lint": "eslint src/**/*.{js,jsx,vue,ts,tsx} --fix"

  • 在vscode编辑器扩展中禁用 Vetur
  • 在vscode编辑器扩展中安装 eslint 插件
  • 在vscode编辑器扩展中安装Vue Language Features (Volar)

  • 进入 vscode 首选项---设置中---扩展---Eslint,勾选Format格式化如下图

npx使用教程:npx 使用教程 - 阮一峰的网络日志 

3、配置 git commit hook 

在代码提交之前,进行代码规则检查能够确保进入git库的代码都是符合代码规则的。但是整个项目上运行lint速度会很慢,lint-staged能够让lint只检测暂存区的文件,所以速度很快。 

  • lint-staged官网:​​​​​​https://github.com/okonet/lint-staged#readme
  • 安装:npx mrm@2 lint-staged(如果安装报错,看这篇文章npx mrm@2 lint-staged执行报错_Daisy__yangyang的博客-CSDN博客

  • 配置 prepare、lint-staged
  • // package.json
    {
      "version": "0.0.0",
      "scripts": {
        "dev": "vite",
        "build": "vue-tsc --noEmit && vite build",
        "serve": "vite preview",
        "tsc": "vue-tsc --noEmit",
        "lint": "eslint ./src/**/*.ts ./src/**/*.vue --cache --fix",
        "prepare": "husky install"
      },
      "lint-staged": {
        "*.{js,jsx,vue,ts,tsx}": [
          "npm run lint",
          // "git add" 之前的版本需要手动把 lint 过程中修改的代码手动 add,新版本不需要了
        ]
      }
    }
    
    ​​​​​​

 4、在开发和构建中进行代码规范校验

插件二选一: 

安装  vite-eslint-plugin:npm install vite-plugin-eslint -D

在 vite.config.ts 配置 插件:

// vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    eslintPlugin({
      cache: false
    })
  ]
})

5、GitCommit规范 

推荐参考:

 统一团队 Git commit 日志标准,便于后续代码 review,版本发布以及日志自动化生成等等。

常用 commit 类型说明:

 

相关工具:

  • commitlint:验证 git commit 日志是否符合规范
    • yarn husky add .husky/commit-msg "",在 husky 目录下新增一个文件 commit-msg
    • 将 commit-msg 文件的 undefined 内容修改为 npx --no -- commitlint --edit $1

       在根目录新建 commitlint.config.js      

    // commitlint.config.js
    
    module.exports = {
      extends: ['@commitlint/config-conventional'],
      rules: {
        'type-enum': [2, 'always', [
          'build',
          'ci',
          'chore',
          'docs',
          'feat',
          'fix',
          'perf',
          'refactor',
          'revert',
          'style',
          'test'
        ]]
        // 'subject-full-stop': [0, 'never'],
        // 'subject-case': [0, 'never']
      }
    }
    //   build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
    //   ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
    //   docs:文档更新
    //   feat:新增功能
    //   fix:bug 修复
    //   perf:性能优化
    //   refactor:重构代码(既没有新增功能,也没有修复 bug)
    //   style:不影响程序逻辑的代码修改(修改空白字符,补全缺失的分号等)
    //   test:新增测试用例或是更新现有测试
    //   revert:回滚某个更早之前的提交
    //   chore:不属于以上类型的其他类型
    
  • Commitizen:辅助编写符合 git commit 规范的工具

6、 Vite中的TS环境说明 

  • 官方文档说明:功能 {#features} | Vite中文网
  • env.d.ts 文件作用:
    • 声明环境变量内容
    • 支持在 ts文件中识别 .vue文件
  • 建议在 package.json 中新增一个 scripts 脚本用来单独执行 TS 类型验证
// package.json

"scripts": {
  ...
  "build": "npm run tsc && vite build",
  "tsc": "vue-tsc -noEmit"
},

-noEmit 表示只验证类型,不输出编译结果。

7、Vue3 中 Ts 支持

官方文档:TypeScript 支持 | Vue.js 

8、Vue3中的script-setup语法 

 官方文档:https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md

9、script-setup中的编译宏 

官方文档:User Guide | eslint-plugin-vue 

.eslintrc.js配置全局变量: 

// .eslintrc.js

module.exports = {
  globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly'
  },
  env: {
    browser: true,
    es2021: true
  },
  extends: [
    'plugin:vue/vue3-strongly-recommended',
    'standard'
  ],
  parserOptions: {
    ecmaVersion: 'latest',
    parser: '@typescript-eslint/parser',
    sourceType: 'module'
  },
  plugins: [
    'vue',
    '@typescript-eslint'
  ],
  rules: {
  }
}

10、 配置转换JSX和TSX 

 渲染函数:渲染函数 | Vue.js

vite 转换 JSX:

        vite/packages/plugin-vue-jsx at main · vitejs/vite · GitHub

        https://vitejs.cn/guide/features.html#jsx

11、初始化 Vue Router 

1、安装 vue-router 

npm install vue-router@4

 2、初始化路由实例

// src\router\index.ts

import { createRouter, RouteRecordRaw, createWebHashHistory } from 'vue-router'

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    component: () => import('../views/home/index.vue')
  },
  {
    path: '/login',
    component: () => import('../views/login/index.vue')
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

// src\main.ts

import { createApp } from 'vue'
import router from './router'
import App from './App.vue'

createApp(App).use(router).mount('#app')

 12、初始化 Vuex

1、安装

npm install vuex@next --save

 2、配置

// src\store\index.ts

import { createStore } from 'vuex'

const store = createStore({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {}
})

export default store

// src\main.ts

import { createApp } from 'vue'
import router from './router'
import store from './store'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'

createApp(App).use(store).use(router).use(ElementPlus).mount('#app')

TS 支持

Vuex 4 版本依然没有很好的解决 TS 类型问题,官方宣称会在 Vuex 5 中提供更好的方案。

13、配置模块路径别名

在 Vite 中支持模块路径别名自定义,参考文档。 

// vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 注意:在 ts 模块中加载 node 核心模块需要安装 node 的类型补充模块:npm i -D @types/node
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  ...
  resolve: {
    alias: {
      '@': path.join(__dirname, 'src')
    }
  }
})

 如果项目中使用了 TS,则还需要告诉 TS 别名的路径,否则 TS 会报错。

// tsconfig.json

{
  "compilerOptions": {
    ...
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  ...
}

 使用示例:

// js

import xxx from '@/api/user.ts'

// html
<img src="@/assets/logo.png">

// css
@import url("@/styles/index.scss");
background: url("@/assets/logo.png");

还有一些插件可以快速配置路径别名:

14、CSS 样式管理 

1、Vite 中的样式支持 

Vite 中对 CSS 的支持:

(1)由于 Vite 的目标仅为现代浏览器,因此建议使用原生 CSS 变量和实现 CSSWG 草案的 PostCSS 插件(例如 postcss-nesting)来编写简单的、符合未来标准的 CSS。

(2)但 Vite 也同时提供了对 .scss, .sass, .less, .styl.stylus 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:

# .scss and .sass
npm install -D sass

# .less
npm install -D less

# .stylus
npm install -D stylus

如果是用的是单文件组件,可以通过 <style lang="sass">(或其他预处理器)自动开启。

注意事项:

  • Vite 为 Sass 和 Less 改进了 @import 解析,以保证 Vite 别名也能被使用。
  • 另外,url() 中的相对路径引用的,与根文件不同目录中的 Sass/Less 文件会自动变基以保证正确性。
  • 由于 Stylus API 限制,@import 别名和 URL 变基不支持 Stylus。
  • 你还可以通过在文件扩展名前加上 .module 来结合使用 CSS modules 和预处理器,例如 style.module.scss

 2、样式作用域

  • 深度作用操作符新语法::deep(<inner-selector>)

3、样式目录结构

variables.scss  # 全局 Sass 变量
mixin.scss      # 全局 mixin
common.scss     # 全局公共样式
transition.scss # 全局过渡动画样式
index.scss      # 组织统一导出

常见的工作流程是,全局样式都写在 src/styles 目录下,每个页面自己对应的样式都写在自己的 .vue 文件之中。

// index.scss

@import './variables.scss';
@import './mixin.scss';
@import './transition.scss';
@import './common.scss';

然后在 main.ts 中导入 index.scss

import "./styles/index.scss"

这里仅仅是加载了全局样式,并不能实现在组件内直接使用全局变量。

3、配置使用全局样式变量

为了能够在组件内直接使用全局变量、mixin 等,需要特殊配置。

具体配置参见 Vite 官方文档:css.preprocessorOptions

这是一个常见的配置参考示例。

css: {
  loaderOptions: {
    // 给 sass-loader 传递选项
    sass: {
      // @/ 是 src/ 的别名
      // 所以这里假设你有 `src/variables.sass` 这个文件
      // 注意:在 sass-loader v8 中,这个选项名是 "prependData"
      additionalData: `@import "@/styles/variables.scss"`
    },
    // 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
    // 因为 `scss` 语法在内部也是由 sass-loader 处理的
    // 但是在配置 `prependData` 选项的时候
    // `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
    // 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
    scss: {
      additionalData: `@import "~@/variables.scss";`
    },
    // 给 less-loader 传递 Less.js 相关选项
    less: {
      // http://lesscss.org/usage/#less-options-strict-units `Global Variables`
      // `primary` is global variables fields name
      globalVars: {
        primary: '#fff'
      }
    }
  }
}

15、和服务端交互

1、基于 axios 封装请求模块

(1)安装 axios: 

npm i axios

 (2)基本配置:

// src/utils/request.ts

import axios from 'axios'

const request = axios.create({
  baseURL: 'https://shop.fed.lagou.com/api/admin' // 基础路径
})

// 请求拦截器
request.interceptors.request.use(
  config => {
    // 统一设置用户身份 Token
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器
request.interceptors.response.use(
  response => {
    // 统一处理响应错误,例如 token 无效、服务端异常等
    return response
  },
  err => {
    return Promise.reject(err)
  }
)

export default request

 (3)封装 API 请求模块:

/**
 * 公共基础接口封装
 */
import request from '@/utils/request'

export const getLoginInfo = () => {
  return request({
    method: 'GET',
    url: '/login/info'
  })
}

 (4)在组件中使用:

import { getLoginInfo } from '@/api/common'
import { onMounted } from '@vue/runtime-core'

onMounted(() => {
  getLoginInfo().then(res => {
    console.log(res)
  })
})

2、关于接口的类型问题

(1)axios 的请求快捷方式都支持使用泛型参数指定响应数据类型。

interface User {
  name: string
  age: number
}

axios.get<User[]>('xxx')

(2)封装泛型请求方法:

// src/utils/request.ts

// 其它代码...

export default <T = any>(config: AxiosRequestConfig) => {
  return request(config).then(res => {
    return (res.data.data || res.data) as T
  })
}

(3)封装请求方法:

// src\api\common.ts

import request from '@/utils/request'
import { ILoginInfo } from './types/common'

export const getLoginInfo = () => {
  return request<ILoginInfo>({
    method: 'GET',
    url: '/login/info'
  })
}

// src\api\types\common.ts

export interface ILoginInfo {
  logo_square: string
  logo_rectangle: string
  login_logo: string
  slide: string[]
}

(4)在组件中调用:

import { getLoginInfo } from '@/api/common'

getLoginInfo().then(data => { // 这里的 data 就有类型了
  console.log(data)
})

16、多环境 baseURL

参考阅读:

# .env.development
# 开发模式下加载的环境变量
VITE_API_BASEURL=http://a.com
# .env.production

# 生产模式下加载的环境变量
VITE_API_BASEURL=http://b.com
// src\utils\request.ts

const request = axios.create({
  // localhost:8080/xxx
  // abc.com/xxx
  // test.com/xxx
  baseURL: import.meta.env.VITE_API_BASEURL
})

17、跨域问题

推荐方案: 

(1) CORS

CORS 全称为 Cross Origin Resource Sharing(跨域资源共享)。这种方案对于前端来说没有什么工作量,和正常发送请求写法上没有任何区别,工作量基本都在后端(其实也没啥工作量,就是配置一些 HTTP 协议)。

(2)服务器代理

能有些后端开发人员觉得配置 CORS 麻烦不想搞,那纯前端也是有解决方案的。

在开发模式下可以下使用开发服务器的 proxy 功能,比如 vite - server.proxy

但这种方法在生产环境是不能使用的。在生产环境中需要配置生产服务器(比如 nginx、Apache 等)进行反向代理。在本地服务和生产服务配置代理的原理都是一样的,通过搭建一个中转服务器来转发请求规避跨域的问题。

(3)在 vie.config.ts配置

// vite.config.js

export default defineConfig({
  server: {
    proxy: {
      // 字符串简写写法
      '/foo': 'http://localhost:4567',
      // 选项写法
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      },
      // 正则表达式写法
      '^/fallback/.*': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/fallback/, '')
      },
      // 使用 proxy 实例
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        configure: (proxy, options) => {
          // proxy 是 'http-proxy' 的实例
        }
      }
    }
  }
})

18、初始化 Element Plus

(1)安装

参考链接:

(2)使用

参考链接:

如果您使用 volar,请在 tsconfig.json 中的 compilerOptions.types 中添加全局组件类型定义。

(3)全局配置

参考链接:

(4)国际化

参考链接:

(5)自定义主题 

参考链接:

(6)图标配置 

参考:Icon 图标 | Element Plus

安装:

$ yarn add @element-plus/icons
# 或者
$ npm install @element-plus/icons

方式一:局部注册使用


<template>
	<!-- 一、SVG 图标默认不携带任何属性 -->
	<edit style="width: 1em; height: 1em; margin-right: 8px;" />
  
	<!-- 二、使用 el-icon 为 SVG 图标提供属性 -->
	<el-icon :size="20" color="#409EFC">
  	<edit></edit>
  </el-icon>

	<!-- 二、通过添加额外的类名 is-loading,你的图标就可以在 2 秒内旋转 360 度,但让你也可以自己改写想要的动画。 -->
	<el-icon :size="20" color="#409EFC">
  	<edit></edit>
  </el-icon>
</template>

<script setup lang="ts">
import { Edit } from '@element-plus/icons'
</script>

 方式二:全局注册使用

// src/plugins/element-plus.ts

import { App } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as icons from '@element-plus/icons'

export default {
  install (app: App) {
    // element-plus 图标
    let k: keyof typeof icons
    for (k in icons) {
      app.component(k, icons[k])
    }

    // element-plus 组件
    app.use(ElementPlus, { size: 'small', zIndex: 2000 })
  }
}

如果您使用 Volar

// src/components.d.ts

declare module 'vue' {
  export interface GlobalComponents {
    Aim: typeof import('@element-plus/icons')['Aim']
    AddLocation: typeof import('@element-plus/icons')['AddLocation']
    Apple: typeof import('@element-plus/icons')['Apple']
    AlarmClock: typeof import('@element-plus/icons')['AlarmClock']
    ArrowDown: typeof import('@element-plus/icons')['ArrowDown']
    ArrowDownBold: typeof import('@element-plus/icons')['ArrowDownBold']
    ArrowLeft: typeof import('@element-plus/icons')['ArrowLeft']
    ArrowLeftBold: typeof import('@element-plus/icons')['ArrowLeftBold']
    ArrowRightBold: typeof import('@element-plus/icons')['ArrowRightBold']
    ArrowUp: typeof import('@element-plus/icons')['ArrowUp']
    Back: typeof import('@element-plus/icons')['Back']
    Bell: typeof import('@element-plus/icons')['Bell']
    Baseball: typeof import('@element-plus/icons')['Baseball']
    Bicycle: typeof import('@element-plus/icons')['Bicycle']
    BellFilled: typeof import('@element-plus/icons')['BellFilled']
    Basketball: typeof import('@element-plus/icons')['Basketball']
    Bottom: typeof import('@element-plus/icons')['Bottom']
    Box: typeof import('@element-plus/icons')['Box']
    Briefcase: typeof import('@element-plus/icons')['Briefcase']
    BrushFilled: typeof import('@element-plus/icons')['BrushFilled']
    Bowl: typeof import('@element-plus/icons')['Bowl']
    Avatar: typeof import('@element-plus/icons')['Avatar']
    Brush: typeof import('@element-plus/icons')['Brush']
    Burger: typeof import('@element-plus/icons')['Burger']
    Camera: typeof import('@element-plus/icons')['Camera']
    BottomLeft: typeof import('@element-plus/icons')['BottomLeft']
    Calendar: typeof import('@element-plus/icons')['Calendar']
    CaretBottom: typeof import('@element-plus/icons')['CaretBottom']
    CaretLeft: typeof import('@element-plus/icons')['CaretLeft']
    CaretRight: typeof import('@element-plus/icons')['CaretRight']
    CaretTop: typeof import('@element-plus/icons')['CaretTop']
    ChatDotSquare: typeof import('@element-plus/icons')['ChatDotSquare']
    Cellphone: typeof import('@element-plus/icons')['Cellphone']
    ChatDotRound: typeof import('@element-plus/icons')['ChatDotRound']
    ChatLineSquare: typeof import('@element-plus/icons')['ChatLineSquare']
    ChatLineRound: typeof import('@element-plus/icons')['ChatLineRound']
    ChatRound: typeof import('@element-plus/icons')['ChatRound']
    Check: typeof import('@element-plus/icons')['Check']
    ChatSquare: typeof import('@element-plus/icons')['ChatSquare']
    Cherry: typeof import('@element-plus/icons')['Cherry']
    Chicken: typeof import('@element-plus/icons')['Chicken']
    CircleCheckFilled: typeof import('@element-plus/icons')['CircleCheckFilled']
    CircleCheck: typeof import('@element-plus/icons')['CircleCheck']
    Checked: typeof import('@element-plus/icons')['Checked']
    CircleCloseFilled: typeof import('@element-plus/icons')['CircleCloseFilled']
    CircleClose: typeof import('@element-plus/icons')['CircleClose']
    ArrowRight: typeof import('@element-plus/icons')['ArrowRight']
    CirclePlus: typeof import('@element-plus/icons')['CirclePlus']
    Clock: typeof import('@element-plus/icons')['Clock']
    CloseBold: typeof import('@element-plus/icons')['CloseBold']
    Close: typeof import('@element-plus/icons')['Close']
    Cloudy: typeof import('@element-plus/icons')['Cloudy']
    CirclePlusFilled: typeof import('@element-plus/icons')['CirclePlusFilled']
    CoffeeCup: typeof import('@element-plus/icons')['CoffeeCup']
    ColdDrink: typeof import('@element-plus/icons')['ColdDrink']
    Coin: typeof import('@element-plus/icons')['Coin']
    ArrowUpBold: typeof import('@element-plus/icons')['ArrowUpBold']
    CollectionTag: typeof import('@element-plus/icons')['CollectionTag']
    BottomRight: typeof import('@element-plus/icons')['BottomRight']
    Coffee: typeof import('@element-plus/icons')['Coffee']
    CameraFilled: typeof import('@element-plus/icons')['CameraFilled']
    Collection: typeof import('@element-plus/icons')['Collection']
    Cpu: typeof import('@element-plus/icons')['Cpu']
    Crop: typeof import('@element-plus/icons')['Crop']
    Coordinate: typeof import('@element-plus/icons')['Coordinate']
    DArrowLeft: typeof import('@element-plus/icons')['DArrowLeft']
    Compass: typeof import('@element-plus/icons')['Compass']
    Connection: typeof import('@element-plus/icons')['Connection']
    CreditCard: typeof import('@element-plus/icons')['CreditCard']
    DataBoard: typeof import('@element-plus/icons')['DataBoard']
    DArrowRight: typeof import('@element-plus/icons')['DArrowRight']
    Dessert: typeof import('@element-plus/icons')['Dessert']
    DeleteLocation: typeof import('@element-plus/icons')['DeleteLocation']
    DCaret: typeof import('@element-plus/icons')['DCaret']
    Delete: typeof import('@element-plus/icons')['Delete']
    Dish: typeof import('@element-plus/icons')['Dish']
    DishDot: typeof import('@element-plus/icons')['DishDot']
    DocumentCopy: typeof import('@element-plus/icons')['DocumentCopy']
    Discount: typeof import('@element-plus/icons')['Discount']
    DocumentChecked: typeof import('@element-plus/icons')['DocumentChecked']
    DocumentAdd: typeof import('@element-plus/icons')['DocumentAdd']
    DocumentRemove: typeof import('@element-plus/icons')['DocumentRemove']
    DataAnalysis: typeof import('@element-plus/icons')['DataAnalysis']
    DeleteFilled: typeof import('@element-plus/icons')['DeleteFilled']
    Download: typeof import('@element-plus/icons')['Download']
    Drizzling: typeof import('@element-plus/icons')['Drizzling']
    Eleme: typeof import('@element-plus/icons')['Eleme']
    ElemeFilled: typeof import('@element-plus/icons')['ElemeFilled']
    Edit: typeof import('@element-plus/icons')['Edit']
    Failed: typeof import('@element-plus/icons')['Failed']
    Expand: typeof import('@element-plus/icons')['Expand']
    Female: typeof import('@element-plus/icons')['Female']
    Document: typeof import('@element-plus/icons')['Document']
    Film: typeof import('@element-plus/icons')['Film']
    Finished: typeof import('@element-plus/icons')['Finished']
    DataLine: typeof import('@element-plus/icons')['DataLine']
    Filter: typeof import('@element-plus/icons')['Filter']
    Flag: typeof import('@element-plus/icons')['Flag']
    FolderChecked: typeof import('@element-plus/icons')['FolderChecked']
    FirstAidKit: typeof import('@element-plus/icons')['FirstAidKit']
    FolderAdd: typeof import('@element-plus/icons')['FolderAdd']
    Fold: typeof import('@element-plus/icons')['Fold']
    FolderDelete: typeof import('@element-plus/icons')['FolderDelete']
    DocumentDelete: typeof import('@element-plus/icons')['DocumentDelete']
    Folder: typeof import('@element-plus/icons')['Folder']
    Food: typeof import('@element-plus/icons')['Food']
    FolderOpened: typeof import('@element-plus/icons')['FolderOpened']
    Football: typeof import('@element-plus/icons')['Football']
    FolderRemove: typeof import('@element-plus/icons')['FolderRemove']
    Fries: typeof import('@element-plus/icons')['Fries']
    FullScreen: typeof import('@element-plus/icons')['FullScreen']
    ForkSpoon: typeof import('@element-plus/icons')['ForkSpoon']
    Goblet: typeof import('@element-plus/icons')['Goblet']
    GobletFull: typeof import('@element-plus/icons')['GobletFull']
    Goods: typeof import('@element-plus/icons')['Goods']
    GobletSquareFull: typeof import('@element-plus/icons')['GobletSquareFull']
    GoodsFilled: typeof import('@element-plus/icons')['GoodsFilled']
    Grid: typeof import('@element-plus/icons')['Grid']
    Grape: typeof import('@element-plus/icons')['Grape']
    GobletSquare: typeof import('@element-plus/icons')['GobletSquare']
    Headset: typeof import('@element-plus/icons')['Headset']
    Comment: typeof import('@element-plus/icons')['Comment']
    HelpFilled: typeof import('@element-plus/icons')['HelpFilled']
    Histogram: typeof import('@element-plus/icons')['Histogram']
    HomeFilled: typeof import('@element-plus/icons')['HomeFilled']
    Help: typeof import('@element-plus/icons')['Help']
    House: typeof import('@element-plus/icons')['House']
    IceCreamRound: typeof import('@element-plus/icons')['IceCreamRound']
    HotWater: typeof import('@element-plus/icons')['HotWater']
    IceCream: typeof import('@element-plus/icons')['IceCream']
    Files: typeof import('@element-plus/icons')['Files']
    IceCreamSquare: typeof import('@element-plus/icons')['IceCreamSquare']
    Key: typeof import('@element-plus/icons')['Key']
    IceTea: typeof import('@element-plus/icons')['IceTea']
    KnifeFork: typeof import('@element-plus/icons')['KnifeFork']
    Iphone: typeof import('@element-plus/icons')['Iphone']
    InfoFilled: typeof import('@element-plus/icons')['InfoFilled']
    Link: typeof import('@element-plus/icons')['Link']
    IceDrink: typeof import('@element-plus/icons')['IceDrink']
    Lightning: typeof import('@element-plus/icons')['Lightning']
    Loading: typeof import('@element-plus/icons')['Loading']
    Lollipop: typeof import('@element-plus/icons')['Lollipop']
    LocationInformation: typeof import('@element-plus/icons')['LocationInformation']
    Lock: typeof import('@element-plus/icons')['Lock']
    LocationFilled: typeof import('@element-plus/icons')['LocationFilled']
    Magnet: typeof import('@element-plus/icons')['Magnet']
    Male: typeof import('@element-plus/icons')['Male']
    Location: typeof import('@element-plus/icons')['Location']
    Menu: typeof import('@element-plus/icons')['Menu']
    MagicStick: typeof import('@element-plus/icons')['MagicStick']
    MessageBox: typeof import('@element-plus/icons')['MessageBox']
    MapLocation: typeof import('@element-plus/icons')['MapLocation']
    Mic: typeof import('@element-plus/icons')['Mic']
    Message: typeof import('@element-plus/icons')['Message']
    Medal: typeof import('@element-plus/icons')['Medal']
    MilkTea: typeof import('@element-plus/icons')['MilkTea']
    Microphone: typeof import('@element-plus/icons')['Microphone']
    Minus: typeof import('@element-plus/icons')['Minus']
    Money: typeof import('@element-plus/icons')['Money']
    MoonNight: typeof import('@element-plus/icons')['MoonNight']
    Monitor: typeof import('@element-plus/icons')['Monitor']
    Moon: typeof import('@element-plus/icons')['Moon']
    More: typeof import('@element-plus/icons')['More']
    MostlyCloudy: typeof import('@element-plus/icons')['MostlyCloudy']
    MoreFilled: typeof import('@element-plus/icons')['MoreFilled']
    Mouse: typeof import('@element-plus/icons')['Mouse']
    Mug: typeof import('@element-plus/icons')['Mug']
    Mute: typeof import('@element-plus/icons')['Mute']
    NoSmoking: typeof import('@element-plus/icons')['NoSmoking']
    MuteNotification: typeof import('@element-plus/icons')['MuteNotification']
    Notification: typeof import('@element-plus/icons')['Notification']
    Notebook: typeof import('@element-plus/icons')['Notebook']
    Odometer: typeof import('@element-plus/icons')['Odometer']
    OfficeBuilding: typeof import('@element-plus/icons')['OfficeBuilding']
    Operation: typeof import('@element-plus/icons')['Operation']
    Opportunity: typeof import('@element-plus/icons')['Opportunity']
    Orange: typeof import('@element-plus/icons')['Orange']
    Open: typeof import('@element-plus/icons')['Open']
    Paperclip: typeof import('@element-plus/icons')['Paperclip']
    Pear: typeof import('@element-plus/icons')['Pear']
    PartlyCloudy: typeof import('@element-plus/icons')['PartlyCloudy']
    Phone: typeof import('@element-plus/icons')['Phone']
    PictureFilled: typeof import('@element-plus/icons')['PictureFilled']
    PhoneFilled: typeof import('@element-plus/icons')['PhoneFilled']
    PictureRounded: typeof import('@element-plus/icons')['PictureRounded']
    Guide: typeof import('@element-plus/icons')['Guide']
    Place: typeof import('@element-plus/icons')['Place']
    Platform: typeof import('@element-plus/icons')['Platform']
    PieChart: typeof import('@element-plus/icons')['PieChart']
    Pointer: typeof import('@element-plus/icons')['Pointer']
    Plus: typeof import('@element-plus/icons')['Plus']
    Position: typeof import('@element-plus/icons')['Position']
    Postcard: typeof import('@element-plus/icons')['Postcard']
    Present: typeof import('@element-plus/icons')['Present']
    PriceTag: typeof import('@element-plus/icons')['PriceTag']
    Promotion: typeof import('@element-plus/icons')['Promotion']
    Pouring: typeof import('@element-plus/icons')['Pouring']
    ReadingLamp: typeof import('@element-plus/icons')['ReadingLamp']
    QuestionFilled: typeof import('@element-plus/icons')['QuestionFilled']
    Printer: typeof import('@element-plus/icons')['Printer']
    Picture: typeof import('@element-plus/icons')['Picture']
    RefreshRight: typeof import('@element-plus/icons')['RefreshRight']
    Reading: typeof import('@element-plus/icons')['Reading']
    RefreshLeft: typeof import('@element-plus/icons')['RefreshLeft']
    Refresh: typeof import('@element-plus/icons')['Refresh']
    Refrigerator: typeof import('@element-plus/icons')['Refrigerator']
    RemoveFilled: typeof import('@element-plus/icons')['RemoveFilled']
    Right: typeof import('@element-plus/icons')['Right']
    ScaleToOriginal: typeof import('@element-plus/icons')['ScaleToOriginal']
    School: typeof import('@element-plus/icons')['School']
    Remove: typeof import('@element-plus/icons')['Remove']
    Scissor: typeof import('@element-plus/icons')['Scissor']
    Select: typeof import('@element-plus/icons')['Select']
    Management: typeof import('@element-plus/icons')['Management']
    Search: typeof import('@element-plus/icons')['Search']
    Sell: typeof import('@element-plus/icons')['Sell']
    SemiSelect: typeof import('@element-plus/icons')['SemiSelect']
    Share: typeof import('@element-plus/icons')['Share']
    Setting: typeof import('@element-plus/icons')['Setting']
    Service: typeof import('@element-plus/icons')['Service']
    Ship: typeof import('@element-plus/icons')['Ship']
    SetUp: typeof import('@element-plus/icons')['SetUp']
    ShoppingBag: typeof import('@element-plus/icons')['ShoppingBag']
    Shop: typeof import('@element-plus/icons')['Shop']
    ShoppingCart: typeof import('@element-plus/icons')['ShoppingCart']
    ShoppingCartFull: typeof import('@element-plus/icons')['ShoppingCartFull']
    Soccer: typeof import('@element-plus/icons')['Soccer']
    SoldOut: typeof import('@element-plus/icons')['SoldOut']
    Smoking: typeof import('@element-plus/icons')['Smoking']
    SortDown: typeof import('@element-plus/icons')['SortDown']
    Sort: typeof import('@element-plus/icons')['Sort']
    SortUp: typeof import('@element-plus/icons')['SortUp']
    Star: typeof import('@element-plus/icons')['Star']
    Stamp: typeof import('@element-plus/icons')['Stamp']
    StarFilled: typeof import('@element-plus/icons')['StarFilled']
    Stopwatch: typeof import('@element-plus/icons')['Stopwatch']
    SuccessFilled: typeof import('@element-plus/icons')['SuccessFilled']
    Suitcase: typeof import('@element-plus/icons')['Suitcase']
    Sugar: typeof import('@element-plus/icons')['Sugar']
    Sunny: typeof import('@element-plus/icons')['Sunny']
    Sunrise: typeof import('@element-plus/icons')['Sunrise']
    Switch: typeof import('@element-plus/icons')['Switch']
    Ticket: typeof import('@element-plus/icons')['Ticket']
    Sunset: typeof import('@element-plus/icons')['Sunset']
    Tickets: typeof import('@element-plus/icons')['Tickets']
    SwitchButton: typeof import('@element-plus/icons')['SwitchButton']
    TakeawayBox: typeof import('@element-plus/icons')['TakeawayBox']
    ToiletPaper: typeof import('@element-plus/icons')['ToiletPaper']
    Timer: typeof import('@element-plus/icons')['Timer']
    Tools: typeof import('@element-plus/icons')['Tools']
    TopLeft: typeof import('@element-plus/icons')['TopLeft']
    Top: typeof import('@element-plus/icons')['Top']
    TopRight: typeof import('@element-plus/icons')['TopRight']
    TrendCharts: typeof import('@element-plus/icons')['TrendCharts']
    TurnOff: typeof import('@element-plus/icons')['TurnOff']
    Unlock: typeof import('@element-plus/icons')['Unlock']
    Trophy: typeof import('@element-plus/icons')['Trophy']
    Umbrella: typeof import('@element-plus/icons')['Umbrella']
    UploadFilled: typeof import('@element-plus/icons')['UploadFilled']
    UserFilled: typeof import('@element-plus/icons')['UserFilled']
    Upload: typeof import('@element-plus/icons')['Upload']
    User: typeof import('@element-plus/icons')['User']
    Van: typeof import('@element-plus/icons')['Van']
    CopyDocument: typeof import('@element-plus/icons')['CopyDocument']
    VideoPause: typeof import('@element-plus/icons')['VideoPause']
    VideoCameraFilled: typeof import('@element-plus/icons')['VideoCameraFilled']
    View: typeof import('@element-plus/icons')['View']
    Wallet: typeof import('@element-plus/icons')['Wallet']
    WarningFilled: typeof import('@element-plus/icons')['WarningFilled']
    Watch: typeof import('@element-plus/icons')['Watch']
    VideoPlay: typeof import('@element-plus/icons')['VideoPlay']
    Watermelon: typeof import('@element-plus/icons')['Watermelon']
    VideoCamera: typeof import('@element-plus/icons')['VideoCamera']
    WalletFilled: typeof import('@element-plus/icons')['WalletFilled']
    Warning: typeof import('@element-plus/icons')['Warning']
    List: typeof import('@element-plus/icons')['List']
    ZoomIn: typeof import('@element-plus/icons')['ZoomIn']
    ZoomOut: typeof import('@element-plus/icons')['ZoomOut']
    Rank: typeof import('@element-plus/icons')['Rank']
    WindPower: typeof import('@element-plus/icons')['WindPower']
  }
}

export {}

18、项目地址

https://gitee.com/daisy_yangyang/shop-admin.git

  • 10
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值