记录一下用 Vue3+TypeScript+Vite 写得项目的总结笔记,温故知新。
SVG 图标 vite-plugin-svg-icons
集成 sass
vite-plugin-mock 在 Vite 项目中模拟数据
axios 二次封装
vue-router 模板路由配置
svg 图标在项目中使用
vite-plugin-svg-icons github 官方文档
安装
npm install vite-plugin-svg-icons -D
配置
// vite.config.ts
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default () => {
  return {
    plugins: [
      createSvgIconsPlugin({
        // 指定需要缓存的图标文件夹
        iconDirs: [path.resolve(process.cwd(), 'src/icons')],
        // 指定symbolId格式
        symbolId: 'icon-[dir]-[name]',
        /**
         * 自定义插入位置
         * @default: body-last
         */
        inject?: 'body-last' | 'body-first'
        /**
         * custom dom id
         * @default: __svg__icons__dom__
         */
        customDomId: '__svg__icons__dom__',
      }),
    ],
  }
}
 
引入
// 在 src/main.ts 内引入注册脚本
import "virtual:svg-icons-register";
 
使用
// /src/components/SvgIcon.vue
<template>
  <svg aria-hidden="true">
    <use :xlink:href="symbolId" :fill="color" />
  </svg>
</template>
<script>
import { defineComponent, computed } from 'vue'
export default defineComponent({
  name: 'SvgIcon',
  props: {
    prefix: {
      type: String,
      default: 'icon',
    },
    name: {
      type: String,
      required: true,
    },
    color: {
      type: String,
      default: '#333',
    },
  },
  setup(props) {
    const symbolId = computed(() => `#${props.prefix}-${props.name}`)
    return { symbolId }
  },
})
</script>
 
// /src/App.vue
<template>
  <div>
    <SvgIcon name="icon1"></SvgIcon>
    <SvgIcon name="icon2"></SvgIcon>
    <SvgIcon name="icon3"></SvgIcon>
    <SvgIcon name="dir-icon1"></SvgIcon>
  </div>
</template>
<script>
import { defineComponent, computed } from 'vue'
import SvgIcon from './components/SvgIcon.vue'
export default defineComponent({
  name: 'App',
  components: { SvgIcon },
})
</script>
 
Typescript 支持
如果使用 Typescript,你可以在 tsconfig.json 内添加
// tsconfig.json
{
  "compilerOptions": {
    "types": ["vite-plugin-svg-icons/client"]
  }
}
 
集成 sass
安装
npm install sass
引入 sass
// main.ts
import "@/styles/index.sass";
 
./styles/index.sass
// 引入清除默认样式
@import './reset.scss'
 
vite.config.js
// 引入scss全局变量配置 preprocessorOptions.scss.javascriptOptions: true
export default defineConfig({
    css: {
        preprocessorOptions: {
            scss: {
                additionalData: '@import "./src/styles/variable.scss"',
            },
        },
    },
});
 
vite-plugin-mock 在 Vite 项目中模拟数据
安装
npm install -D vite-plugin-mock mockjs
配置与使用
// vite.config.js
import { UserConfigExport, ConfigEnv } from "vite";
import { viteMockServe } from "vite-plugin-mock";
import vue from "@vitejs/plugin-vue";
export default ({ command }: ConfigEnv): UserConfigExport => {
    return {
        plugins: [
            vue(),
            viteMockServe({
                // default
                mockPath: "mock",
                localEnabled: command === "serve",
            }),
        ],
    };
};
 
// mock/test.ts
import { MockMethod } from 'vite-plugin-mock'
export default [
  {
    url: '/api/get',
    method: 'get',
    response: ({ query }) => {
      return {
        code: 0,
        data: {
          name: 'vben',
        },
      }
    },
  },
  {
    url: '/api/post',
    method: 'post',
    timeout: 2000,
    response: {
      code: 0,
      data: {
        name: 'vben',
      },
    },
  },
  {
    url: '/api/text',
    method: 'post',
    rawResponse: async (req, res) => {
      let reqbody = ''
      await new Promise((resolve) => {
        req.on('data', (chunk) => {
          reqbody += chunk
        })
        req.on('end', () => resolve(undefined))
      })
      res.setHeader('Content-Type', 'text/plain')
      res.statusCode = 200
      res.end(`hello, ${reqbody}`)
    },
  },
] as MockMethod[]
 
axios 二次封装
安装
npm install axios
配置使用
// utils/request.js
//创建axios实例, baseURL等可以从配置读取
const instance = axios.create({
  baseURL: '',
  timeout: 1000,
  headers: { 'X-Custom-Header': 'foobar' }
});
//添加请求/响应拦截器,
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
  //config配置对象,headers属性请求头,经常给服务端携带公共参数
  // 在发送请求之前做些什么
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么 简化数据 return response.data
  return response;
}, function (error) {
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error);
 
API 接口统一管理
// api/user/index.ts,api/user/type.ts统一管理用户相关接口
//api/user/index.ts
import request from "@/utils/request";
import { loginForm, loginResponseData, userResponseData } "./type"
enum API {//统一管理接口
  LOGIN_URL = "/user/login",
  USERINFO_URL = "/user/info",
}
//暴露请求函数
export const reqLogin = (data: loginForm)=request.post<any, loginResponseData > (API.LOGIN_URL, data)
export const reqUserInfo = () = request.post<any, userResponseData>(API.USERINFO_URL, data)
//api/user/type.ts
//接口请求数据类型
export interface loginFrom {
  username: string,
  password: string
}
interface dataType {
  token: string
}
//接口返回数据类型
export interface loginResponseData {
  code: number,
  data: dataType
}
//服务器返回用户相关信息
interface userInfo {
  useeId: number,
  avatar: string,
  username: string,
  password: string,
  roles: string[]
  //……
}
interface user {
  checkUser: userInfo
}
export interface userResponseData {
  code: number,
  data: user
}
 
vue-router 模板路由配置
安装
npm install vue-router
配置使用
// views/login/index.vue,views/home/index.vue, views/404/index.vue
// router/index.ts
import { createRouter, createWebHashHistory } from "vue-router";
import { constantRoute } from "./routes.ts";
let router = createRouter({
    history: createWebHashHistory(),
    routers: constantRoute,
    //滚动行为
    scrollBehavior() {
        return { left: 0, top: 0 };
    },
});
export default router;
 
// router/routes.ts
export const constantRoute = [
    { path: "/login", name: "login", component: () => import("@/views/login/index.vue") },
    { path: "/", name: "layout", component: () => import("@/views/home/index.vue") },
    { path: "/404", name: "404", component: () => import("@/views/404/index.vue") },
    { path: "/:pathMatch(.*)*", name: "any", redirect: "404" },
];
 
// main.ts 注册路由
import router from "./router";
app.use(router);
 
// App.vue
<router-view></router-view>