You don't have javascript enabled. Good luck! :(

欢迎页

Welcome to Ganace's Blog


欢迎您来到Ganace 的个人博客。

在茫茫互联网的海洋里能够遇见,实在是一份不小的幸运。

诚挚地向您问候一声:您好,朋友!

这里是属于Ganace个人的隐秘小空间,记录了工作学习中遇到的知识点与灵感,以及生活中的碎碎念与吐槽突如其来的中二病尬尬的文艺时间锻炼腹肌的时刻惊喜的小发现等等。

想要在自己的平淡无奇的人生长河中留下些什么,

或者只是为了拯救老人家岌岌可危的记忆力,

仅此而已。

来到此地,分享与你。

也期待与您的再次相遇!

Share with Me


有任何的分享或者建议与吐槽,都可以Email我:ganace@foxmail.com

欢迎您的来信!

【Vue】Vue3+TypeScript+Vite项目笔记

  Mar 23, 2024     Ganace     Front-end-Foundation

Vue
TypeScript
Vite

记录一下用 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>