Vue3 + Element Plus权限管理系统前端篇(一):项目配置

本篇文章开始介绍项目前端部分的开发。项目将使用 Vue 的最新版本 vue3.5 版本进行开发,UI 则使用ElementPlus,样式部分将采用scsstailwindcss进行编写,状态管理使用Pinia等等,后续需要什么直接进行安装即可。ok,接下来便开始后台管理系统的搭建吧!

项目配置

项目开始首先需要做到就是创建一个 vue3 项目,这里使用 vite 进行创建npm create vite选择 TypeScript 版本创建就行了,然后安装vue-routeraxiospinia等等,具体操作就不一一细说了,相信聪明的你早都会了。

可能有的小伙伴对 tailwindcss 不太熟悉,这里单独说一下如何配置tailwindcss

首先简单看一下tailwindcss干嘛的,当我们引入了tailwindcss后,我们只需要在元素中中添加class即可实现我们想要的样式。例如:

<div class="flex items-center justify-center h-screen bg-gray-100">text</div>

表示这个 divflex 盒子,同时设置了align-items: center;justify-content: center且高度撑满整个屏幕,以及背景颜色为色调 100(色调越高,颜色越深)的 gray。有的小伙伴可能会问,我不熟悉 tailwind类名咋写怎么办? 很简单,你直接问gpt就行了。

Vue3 + Element Plus权限管理系统前端篇(一):项目配置
image.png

然后看一下如何在项目中引入tailwindcss,首先安装 tailwindcss 以及它使用到的包

npm install tailwindcss postcss autoprefixer -D

然后执行

npx tailwindcss init -p

你会发现项目中会生成postcss.config.jstailwind.config.js两个配置文件,修改一下tailwind.config.js

/** @type {import('tailwindcss').Config} */
export default {
  content: ["./index.html""./src/**/*.{vue,js,ts,jsx,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
};

src 下新建 index.css

@tailwind base;
@tailwind components;
@tailwind utilities;

最后在main.ts引入index.css就大功告成了

项目结构

简单说一下项目结构,后续新增的话会更新一下

  1. 页面文件放在 views 文件下,且命名方式为文件夹/index.vue

  2. 组件写在components目录下,命名统一采用大驼峰格式

  3. 不含有响应式 api 的工具函数写在utils文件下,命名方式为小驼峰。含有响应式 api 的工具则称之为hook函数,写在hooks文件夹下,命名方式为use-xxx/index.ts,导出函数名为useXxx

  4. 请求接口统一写在src/api目录下,且根据使用场景区分目录

axios 请求封装

项目使用axios来发送http请求,目前大多数项目都会对其进行一次封装进行请求和响应的拦截以及一些基本配置等。前期我写过一篇文章一篇文章带你详细了解 axios 的封装[1],感兴趣的可以参考一下,这里就不过多赘述直接贴代码了(目录:utils/http/index)

import axios, {
  AxiosInstance,
  AxiosResponse,
  InternalAxiosRequestConfig,
from "axios";
import { ElMessage, ElLoading } from "element-plus";
import router from "@/router";
import { Storage } from "@/utils/storage";
const loadingInstance = ElLoading.service;
let requestCount = 0;
const showLoading = () => {
  requestCount++;
  if (requestCount === 1) loadingInstance();
};
const closeLoading = () => {
  requestCount--;
  if (requestCount === 0) loadingInstance().close();
};

const service: AxiosInstance = axios.create({
  method"get",
  baseURLimport.meta.env.VITE_APP_API,
  headers: {
    "Content-Type""application/json;charset=utf-8",
  },

  timeout10000,
});
//请求拦截

declare module "axios" {
  interface AxiosRequestConfig<D = any> {
    loading?: boolean;
    isToken?: boolean;
  }
  interface InternalAxiosRequestConfig<D = any, T = any> {
    loading?: boolean;
    isToken?: boolean;
  }
  interface AxiosInstance {
    (config: AxiosRequestConfig): Promise<any>;
  }
}

const requestMap = new Map();
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig<any>) => {
    const controller = new AbortController();
    const key = config.data + config.url;
    config.signal = controller.signal;
    if (requestMap.has(key)) {
      requestMap.get(key).abort();
      requestMap.delete(key);
    } else {
      requestMap.set(key, controller);
    }

    const { loading = true, isToken = true } = config;

    if (loading) showLoading();
    if (Storage.get("token") && isToken) {
      config.headers["Authorization"] = "Bearer " + Storage.get("token"); // 让每个请求携带自定义token 请根据实际情况自行修改
    }

    return config;
  },
  (error) => {
    console.log(error);
  }
);

service.interceptors.response.use(
  (res: AxiosResponse<any, any>) => {
    const { data, config } = res;

    const { loading = true } = config;
    if (loading) closeLoading();

    if (data.code != 200) {
      ElMessage({
        message: data.describe,
        type"error",
      });
      if (data.code === 401 || data.code === 400) {
        //登录状态已过期.处理路由重定向
        Storage.remove("token");
        router.push("/");
      }
      throw new Error(data.describe);
    }
    return data;
  },
  (error) => {
    closeLoading();
    let { message } = error;
    if (message == "Network Error") {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      message = "系统接口" + message.substr(message.length - 3) + "异常";
    }
    ElMessage({
      message: message,
      type"error",
    });
    router.push("/login");
    return Promise.reject(error);
  }
);
export default service;

相关请求接口统一写在api目录下,以登录接口为例,在api/login/index.ts

import request from "@/utils/http/index";
import { LoginVo } from "./types/login.vo";
export const login = (data: LoginVo) => {
  return request({
    url"/user/login",
    data,
    isTokenfalse,
    method"post",
  });
};

其中LoginVo类型用来描述我们需要传递后台的参数

export type LoginVo = {
  username: string;
  password: string;
  id: string;
  captcha: string;
};

最后页面中直接导入login即可发起请求。

前端部分相关配置就介绍到这里,当然这里肯定是不全的,后续会慢慢完善。最后相关代码地址[2]奉上,(既见代码,为何不赞!是因为不喜欢吗?!)

标注地址
[1]

https://juejin.cn/post/7239953874950373436

[2]

https://github.com/qddidi/fs-admin/commit/7d4c08a27d4f5fc974f406fe5183ee02a48e4c8a


原文始发于微信公众号(web前端进阶):Vue3 + Element Plus权限管理系统前端篇(一):项目配置

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/305735.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!