Vite+ts+springboot项目集成2

发布时间 2023-09-24 21:42:55作者: 澜璨

项目集成

集成element-plus

官网地址:
安装图标库

pnpm install element-plus @element-plus/icons-vue

image-20230921093740428

入口文件main.ts全局安装element-plus,element-plus默认支持语言英语设置为中文

import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css'
//@ts-ignore忽略当前文件ts类型的检测否则有红色提示(打包会失败)
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
app.use(ElementPlus, {
    locale: zhCn
})

src别名的配置

在开发项目的时候文件与文件关系可能很复杂,因此我们需要给src文件夹配置一个别名!!!

// 在vite.config.ts文件,写入如下配置

import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
    plugins: [vue()],
    resolve: {
        alias: {
            "@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src
        }
    }
})

TS编译配置,ts.config.json文件夹下

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "./", // 解析非相对模块的基地址,默认是当前目录
    "paths": { //路径映射,相对于baseUrl
      "@/*": ["src/*"] 
    }
  }
}

image-20230921100916449

环境变量配置

项目开发过程中,至少会经历开发环境、测试环境和生产环境(即正式环境)三个阶段。不同阶段请求的状态(如接口地址等)不尽相同,若手动切换接口地址是相当繁琐且易出错的。于是环境变量配置的需求就应运而生,我们只需做简单的配置,把环境状态切换的工作交给代码。

  • 开发环境(development)
    顾名思义,开发使用的环境,每位开发人员在自己的dev分支上干活,开发到一定程度,同事会合并代码,进行联调。

  • 测试环境(testing)
    测试同事干活的环境啦,一般会由测试同事自己来部署,然后在此环境进行测试

  • 生产环境(production)
    生产环境是指正式提供对外服务的,一般会关掉错误报告,打开错误日志。(正式提供给客户使用的环境。)

  • 注意:一般情况下,一个环境对应一台服务器,也有的公司开发与测试环境是一台服务器!!!

  • 项目根目录分别添加 开发、生产和测试环境的文件!

    .env.development // 开发环境配置文件
    .env.production // 生产环境配置文件
    .env.test // 测试环境配置文件
    

这些环境下的配置文件,你可以定义相应的变量,变量在不同的环境下,可以通过不同的手段去获取他

development测试代码

# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development' // 开发环境
VITE_APP_TITLE = 'wavesbright' // 设置的变量
VITE_APP_BASE_API = '/dev-api' // 

production测试代码

# 生产环境
NODE_ENV = 'production'
VITE_APP_TITLE = 'wavesbright'
VITE_APP_BASE_API = '/prod-api'

test测试代码

# 测试环境
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'test'
VITE_APP_TITLE = 'wavesbright'
VITE_APP_BASE_API = '/test-api'

在package.json当中添加配置

 "scripts": {
    "dev": "vite --open",
    "build:test": "vue-tsc && vite build --mode test",
    "build:pro": "vue-tsc && vite build --mode production",
    "preview": "vite preview"
  },

获取环境变量

image-20230921102056343

image-20230921102108540

SVG图标配置阿里矢量图标

官网地址

  • 在开发项目的时候经常会用到svg矢量图,而且我们使用SVG以后,页面上加载的不再是图片资源,
  • 这对页面性能来说是个很大的提升,而且我们SVG文件比img要小的很多,放在项目中几乎不占用资源。

安装SVG依赖插件

pnpm install vite-plugin-svg-icons -D

vite.config.ts中配置插件

import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
      // 初始化插件对象
    createSvgIconsPlugin({
      iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
      symbolId: 'icon-[dir]-[name]',
    }),
  ],
  resolve: {
    alias: {
      '@': path.resolve('./src'), // // 相对路径别名配置,使用 @ 代替 src
    },
  },
})

以后矢量图标就放在src/assets/icons

入口文件导入main.ts

import 'virtual:svg-icons-register'

测试在该框架中SVG图标如何使用

先去阿里随便下个图标,我选了个锤子

image-20230921103553732

目录查看

image-20230921103623521

svg标签使用

  1. 我们使用矢量图标需要通过svg标签

  2. svg标签是图标外层容器节点,内部需要与use标签结合使用

  3. 通过use的属性 xlink:href属性。指定你所用的图标,内部务必以#icon-图标名进行定义

    • 格式

    • <use xlink:href="#icon-sledgehammer"></use>
      
  4. use标签的fill属性,可以设置图片颜色

  5. 通过在svg当中设置样式,可以该表图标大小

来,将这个锤子设置为蓝色,50px大小

好好好,遇到个问题,我图片加载不出来,但是通过访问图片路径可以访问到,离谱

image-20230921111213791

设置svg图标配置,但是读不出来

image-20230921111233763

image-20230921111240619

我找到问题了,是xlink:href 不是 xlink-href.我真的日了

我先封装一下这个SVG图标,方便以后调用,虽然现在用不起

在components文件夹下创建SVGIcon文件夹,创建index.vue文件,我们封装就在这里封装

如何封装

<template>
  <div>
    <svg :style="{ width: width, height: height }">
      <use :xlink:href="prefix + name" :fill="color"></use>
    </svg>
  </div>
</template>

<script setup lang="ts">
defineProps({
  //xlink:href属性值的前缀
  prefix: {
    type: String,
    default: '#icon-'
  },
  //svg矢量图的名字
  name: String,
  //svg图标的颜色
  color: {
    type: String,
    default: ""
  },
  //svg宽度
  width: {
    type: String,
    default: '16px'
  },
  //svg高度
  height: {
    type: String,
    default: '16px'
  }

})
</script>
<style scoped></style>

封装完成后,在需要使用组件的地方导入即可

<template>
  <div>
    SVG测试
    <!-- svg:图标外层容器节点,内部需要与use标签结合使用 -->
    <svg style="width: 50px; height: 50px;">
      <!-- 通过use的属性 xlink:href属性。指定你所用的图标 -->
      <use xlink:href="#icon-chuizi"></use>
    </svg>

    <!-- 封装的图标组件测试 -->
    <h2>这是组件封装</h2>
    <SvgIcon name="chuizi" color="pink" width="50px" height="50px"></SvgIcon>
  </div>
</template>

<script setup lang="ts">
  import SvgIcon from "@/components/SVGIcon/index.vue";

</script>

<style scoped>

</style>

image-20230921165828203

但是这样也很麻烦,我们需要更高效的封装方式,也就是将其注册为全剧组件调用,不需要通过import关键字

然后在main.ts当中注册,不过这样也不行,component下有多少组件就需要在main.ts当中注册多少次,也不是长远之计,所以

在components文件夹下,创建一个index.ts文件,这个文件对外暴露,使用的语法是 对外暴露插件对象

对外暴露插件对象

// components/index.ts

// 引入需要注册的组件

// 图标库
import SvgIcon from './SVGIcon/index.vue'

// 创建一个对象存储以后需要注册的全局组件对象
const allGloabComonent = {SvgIcon}
export default {
    // 下载安装全局的组件,一次到位,务必叫做install,app的实例也在这里
    install(app){
        // 我们可以通过其component方法注册组件
        // 通过obj.keys返回的数组.进行打点注册
        Object.keys(allGloabComonent).forEach(key=>{
            // 注册项目的全部的全局组件
            app.component(key,allGloabComonent[key]);
        })
    }
}

main.ts当中注册这个全局组件

// yinru 自定义插件对象:注册整个项目的全局组件
import gloablComonent from "@/components";
// 安装自定义插件
app.use(gloablComonent);

集成sass

我们目前在组件内部已经可以使用scss样式,因为在配置styleLint工具的时候,项目当中已经安装过sass sass-loader,因此我们再组件内可以使用scss语法!!!需要加上lang=“scss”

<style scoped lang="scss"></style>

接下来我们为项目添加一些全局的样式

在src/styles目录下创建一个index.scss文件,当然项目中需要用到清除默认样式,因此在index.scss引入reset.scss

去npm官网当中进入reset.sass网址,在里面copy清除全局样式的sass代码

image-20230921172531980

image-20230921173455970

在style文件下新建,reset.scss,将代码copy进去

在index.scss下,引入我们的全局清除样式

image-20230921173744759

给scss配置全局变量,因为你会发现在src/styles/index.scss全局样式文件中没有办法使用$变量.因此需要给项目中引入全局变量$.

在style/variable.scss创建一个variable.scss文件,以后的全局变量就扔这里

image-20230921174229365

在vite.config.ts当中配置

export default defineConfig((config) => {
 // scss全局变量配置 全局变量配置在/variable.scss
	css: {
      preprocessorOptions: {
        scss: {
          javascriptEnabled: true,
          additionalData: '@import "./src/styles/variable.scss";',
        },
      },
    },
	}
}

vite.config.ts

/*
 * @Author: WavesBright 1336959829@qq.com
 * @Date: 2023-09-21 01:24:43
 * @LastEditors: WavesBright 1336959829@qq.com
 * @LastEditTime: 2023-09-21 17:44:12
 * @FilePath: \waves-ts-runtine\vite.config.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// 引入SVG矢量图标库
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
    plugins: [vue(),
    createSvgIconsPlugin({
        // 以后矢量图标就放在src/assets/icons
        iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
        symbolId: 'icon-[dir]-[name]',

    }),
    ],
    resolve: {
        alias: {
            "@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src
        }
    },
    // 配置全局变量
    // scss全局变量配置 全局变量配置在/variable.scss
    css: {
        preprocessorOptions: {
            scss: {
                javascriptEnabled: true,
                additionalData: '@import "./src/styles/variable.scss";',
            },
        },
    },
})

image-20230921174459177

测试

image-20230921174631362

更优雅的写法,待日后精进

mack接口

造一些假的数据

安装

pnpm install -D vite-plugin-mock mockjs

在 vite.config.js 配置文件启用插件。

  • 从这个插件 vite-plugin-mock 引入了一个函数 viteMockServe
  • 他的配置项是暴露一个箭头函数,箭头函数返回一个配置对象
  • 我们原先的对外暴露的是一个配置对象,而不是返回配置对象

将原先的vite.congif.ts文件留存一下

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// 引入SVG矢量图标库
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
    plugins: [vue(),
    createSvgIconsPlugin({
        // 以后矢量图标就放在src/assets/icons
        iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
        symbolId: 'icon-[dir]-[name]',

    }),
    ],
    resolve: {
        alias: {
            "@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src
        }
    },
    // 配置全局变量
    // scss全局变量配置 全局变量配置在/variable.scss
    css: {
        preprocessorOptions: {
            scss: {
                javascriptEnabled: true,
                additionalData: '@import "./src/styles/variable.scss";',
            },
        },
    },
})

新的

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// 引入SVG矢量图标库
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
// 引入Mock帮助我们构建假的接口,提供的方法
import { viteMockServe } from 'vite-plugin-mock'
// 将原先的对外暴露进行修改
export default defineConfig((command) => {
    return {
        plugins: [vue(),
        createSvgIconsPlugin({
            // 以后矢量图标就放在src/assets/icons
            iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
            symbolId: 'icon-[dir]-[name]',
        }),
        viteMockServe({
            // 这行代码保证开发阶段可以使用MOck接口
            localEnabled: command === 'serve',
        }),
        ],
        resolve: {
            alias: {
                "@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src
            }
        },
        // 配置全局变量
        // scss全局变量配置 全局变量配置在/variable.scss
        css: {
            preprocessorOptions: {
                scss: {
                    javascriptEnabled: true,
                    additionalData: '@import "./src/styles/variable.scss";',
                },
            },
        },
    }
})

遇到bug

image-20230922175901988

image-20230922175916281

解决方法,打开pnpm-lock.yaml文件,找到vite-plugin-mock这个条目,将版本修改为2.9.8

image-20230922180013734

通过pnpm重新安装

pnpm install vite-plugin-mock@2.9.8 --save-dev

接下来

在根目录创建mock文件夹:去创建我们需要mock数据与接口!!!

在mock文件夹内部创建一个user.ts文件

  • 函数解析,这里有一个createUserList,该方法返回两个数组,数组当中存储着两个用户的信息
  • 对外暴露了一个数组,这个数组里面有俩接口
    • 登录的假接口
    • 获取用户信息的假接口
//用户信息数据
function createUserList() {
    return [
        {
            userId: 1,
            avatar:
                'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
            username: 'admin',
            password: '111111',
            desc: '平台管理员',
            roles: ['平台管理员'],
            buttons: ['cuser.detail'],
            routes: ['home'],
            token: 'Admin Token',
        },
        {
            userId: 2,
            avatar:
                'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
            username: 'system',
            password: '111111',
            desc: '系统管理员',
            roles: ['系统管理员'],
            buttons: ['cuser.detail', 'cuser.user'],
            routes: ['home'],
            token: 'System Token',
        },
    ]
}

export default [
    // 用户登录接口
    {
        url: '/api/user/login',//请求地址
        method: 'post',//请求方式
        response: ({ body }) => {
            //获取请求体携带过来的用户名与密码
            const { username, password } = body;
            //调用获取用户信息函数,用于判断是否有此用户
            const checkUser = createUserList().find(
                (item) => item.username === username && item.password === password,
            )
            //没有用户返回失败信息
            if (!checkUser) {
                return { code: 201, data: { message: '账号或者密码不正确' } }
            }
            //如果有返回成功信息
            const { token } = checkUser
            return { code: 200, data: { token } }
        },
    },
    // 获取用户信息
    {
        url: '/api/user/info',
        method: 'get',
        response: (request) => {
            //获取请求头携带token
            const token = request.headers.token;
            //查看用户信息是否包含有次token用户
            const checkUser = createUserList().find((item) => item.token === token)
            //没有返回失败的信息
            if (!checkUser) {
                return { code: 201, data: { message: '获取用户信息失败' } }
            }
            //如果有返回成功信息
            return { code: 200, data: {checkUser} }
        },
    },
]

登录接口的一些参数解释,毕竟有小半年没有写过对应的逻辑了,加深一下印象

  • url,请求地址,method,请求方式,response是响应体配置
  • response是一个匿名函数,有一个参数body,获取body当中的账号密码
  • 调用上述的函数createUserLsit,会返回一个数组,通过数组的find方法进行账密验证
  • 有则带回用户的信息,存储在数组当中,没有就提示报错

安装axios

pnpm install axios

在入口文件当中测试,matin.ts

image-20230922181328771

启动项目进行测试

image-20230922182244889

axios二次封装

在开发的时候,一般会对axios进行二次封装

目的是

1:使用请求拦截器,可以在请求拦截器中处理一些业务(开始进度条、请求头携带公共参数)

2:使用响应拦截器,可以在响应拦截器中处理一些业务(进度条结束、简化服务器返回的数据、处理http网络错误)

根目录下创建utils/request.ts

// 对axios进行二次封装:目的是使用请求与响应拦截器
import axios from "axios"
// empls的一个错误消息提示组件
import { ElMessage } from "element-plus"

// 1、利用axios对象的creat方法,去创建axios实例(可以设置其他配置:例如基础路径,超时时间等等)
// 使用create创建的axios可以写一些其他的配置
let request = axios.create({
    baseURL: "http://localhost:5173/admin", // 基础路径,我重构的项目基础路径是admin
    timeout: 5000 // 请求超时时间
});

// 2、给axios实例添加请求和响应拦截器
// 使用请求拦截器,发请求之前触发拦截器,触发的时候,回调函数会传进来一个配置对象config
request.interceptors.request.use((config) => {
    // 这个config需要返回,不然请求发不出去
    // config配置对象,有一个headers属性请求头,经常给服务器端携带公共的参数
    return config;
})

// 3、配置一下响应拦截器,成功回调和失败回调
request.interceptors.response.use(
    (response) => {
        // 这里看具体配合,我传递回来的参数是什么,可能需要添加后缀        
        return response.data; // 这个data包含了我在springboot当中定义的JsonResult类型
    }, (error) => {
        // 失败回调,处理http网络错误的回调
        // 定义一个变量,存储网络错误信息
        let message = '';
        let status = error.response.state
        switch (status) {
            case 401:
                message = 'token过期'
                break
            case 403:
                message = '无权访问'
                break
            case 404:
                message = '请求地址错误'
                break
            case 500:
                message = '服务器出现问题'
                break
            default:
                message = '无网络'
        }
        // 提示错误信息
        ElMessage({
            type:"error",
            message
        })
        // 终结我们的promise量
        return Promise.reject(error);
    })
// 暴露组件,供外部调用
export default request;