vite + vue3 + 封装axios + 封装loading + 封装返回顶部

前言

​前期回顾    ​      

vite + vue3 + ts配置《企业级项目》二次封装el-table、分页_0.活在风浪里的博客-CSDN博客封装的功能有哪些?分页、表格排序、文字居中、溢出隐藏、操作列、开关、宽、最小宽、type类型(selection/index/expand)、格式化 、不同页面不同操作列、vuex、vue持久化插件、(此处没有接口所以用到,还涉及了query与params传值区别)子组件说思路:data数据请求接口拿到,表头数据一般也是后台接口,如没,前台可自定义自己写......https://blog.csdn.net/m0_57904695/article/details/125613767?spm=1001.2014.3001.5501


目录

前言

 我要实现什么效果?

代码简单吗?

念及此

一、封装axiso前先配置环境变量

第一步: 配置环境变量

第二步:封装axios

二:封装loading

​ loading.vue 

 index.ts

 在main.ts引入index.ts

 三:封装返回顶部

 MyBackTop.vue

 index.ts

在main.ts引入index.ts

结语 


 我要实现什么效果?

  • 全局封装一次!

  • 项目中切换路由显示loading,

  • 发起axios显示loading,

  • 每个页面显示返回顶部

  

代码简单吗?

  • 极简

念及此

  • 正文开始

一、封装axiso前先配置环境变量

  • 因为真实项目中需要不同环境测试的

第一步: 配置环境变量

 在根目录新建三个文件

.env.development

 NODE_ENV='development'

 .env.production

  NODE_ENV='production'

.env.staging

NODE_ENV='production'

 

 完成!

第二步:封装axios

在src下新建newwork文件夹 并在里面新建4个文件

解释: 

  •  api.js 封装的是api接口,在项目中大量用到接口不能分散写在各处、不易维护
  • baseUrl.s 匹配环境变量  比如开发环境则使用线上接口,生产环境则使用生产接口
  • http.js 创建axiso实例写入请求拦截响应拦截
  • request.js 封装的是请求方法,在项目中大量用到接口,所以将请求方法也封装

正文: 

 一:先写baseUrl.js 匹配环境变量 

let baseURL = "";
if (process.env.NODE_ENV === "development") {
    // 开发环境  因为我这里写了配置跨域的重定路径所以是api 如下图
    baseURL = "/api";

} else if (process.env.NODE_ENV === "production") {
    // 正式环境 真正的上线网址 不是跨域别名路径,在network不显示
    baseURL = "";
} else {
    // 测试环境
    baseURL = "";
}
export default baseURL;

二: 网址配好后写 http.js 创建axiso实例

import axios from "axios";
// 导入element-ElMessage 弹框
// import { ElMessage } from "element-plus";
// 导入配置的环境变量url
import baseURL from "./baseURL";
// 导入路由,没有this,使用路由实例跳转
import router from "../route/router.ts";
// 导入main全局配置文件
import app from "../../src/main";
// 开启loading
app.config.globalProperties.$loading.showLoading();
// 创建axios实例
const http = axios.create({
  baseURL, //配置了跨域,起了别名api,在baseBUL用了别名,这里使用baseURL,配置在下面vue.config.js
  timeout: 6000,
  withDirectives: true, // 是否携带cookies
});
// 请求拦截
http.interceptors.request.use(
  (config) => {
    // 在请求发送之前做一些处理 config是axios的配置对象
    // console.log(config);
    //  携带token
    config.headers["Authorization"] =
      "Bearer " + JSON.parse(localStorage.getItem("remember_token")) || null;
    // 配置完成将config返回
    return config;
  },
  (err) => {
    // 当请求失败时做一些处理 抛出错误
    throw new Error(err);
  }
);

// 响应拦截
http.interceptors.response.use(
  (res) => {
    // 在返回响应之前做一些处理 res是axios的配置对象
    // console.log(res);

    // 关闭loading
    app.config.globalProperties.$loading.hideLoading();
    // 根据后台状态码统一封装提示信息 就不需要在页面接口在单独写了
    // 这里根据实际接口的嵌套情况和状态码来写 这里只是我的接口嵌套情况
    let { status, msg } = res.data.meta;
    //key = value  status等于200就执行200下的代码 执行完break退出循环
    switch (status) {
      case 200:
        ElMessage({
          showClose: true,
          message: msg,
          type: "success",
        });
        break;

      case 401:
        ElMessage({
          showClose: true,
          message: "未授权",
          type: "error",
        });
        // console.log(this);
        // this是undefined所以引入路由;
        router.push("/login"); //未授权跳转到login
        break;
    }
    // 这里根据接口返回的数据嵌套结构来返回 比如我的接口返回的是{data:{message:{}}}
    return res.data.message;
  },
  (err) => {
    // 当响应失败时做一些处理 抛出错误
    throw new Error(err);
  }
);
// 导出 http实例 方便调用
export default http;

三:请求封装好了 封装请求方法 request.js

import http from "./http";
// post请求: 传参数没有明确规定使用params接受参数就是要使用data请求体接受,get请求要使用params接受
// put 也相当与post请求,如果报参数错误,就是接受参数的请求体错了post/put用data,get请求用params
function request({ method = 'get', url, data = {}, params = {} }) {
    return http({
        method,
        url,
        data,
        params
    })
}

export default request;

四:请求方法好了 封装api.js

// 导入请求的方法

// 不使用箭头函数
// export function home() {
//     return request({ url: '/home', })
// }

import request from "./request";
// 用户登陆的接口  post请求使用data请求体 默认封装的get 如果是get请求不需要写methiod
 export const login = (data) => request({ method: "post", url: '/login', data: data });

// 获取用户列表的接口 ,需要有默认参数. pagenum: 1,pagesize: 10,,所以要接收,
 export const getUserList = (params) => request({ url: '/users', params });

// put请求修改用户id users/:uId/state/:type
    export const getEdit = (data) => request({
     method: "put",
     data,
     url: "users/" + data.uid + "/state/" + data.type,
   })

export const order = () => request({ url: "/home/floordata" });

二:封装loading

 在src下的 components 新建 俩个文件

 

loading.vue 

<template>
  <div id="loading" v-show="visible">
    <div class="circle"></div>
    <br />
    疯狂加载中...
  </div>
</template>

<script>
import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "Loading",
  setup() {
    // 控制组件的状态
    let visible = ref(false);

    // 显示组件
    let showLoading = () => {
      visible.value = true;
    };
    // 隐藏组件
    let hideLoading = () => {
      visible.value = false;
    };

    return { visible, showLoading, hideLoading };
  },
});
</script>
<style scoped>
#loading {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
}
@keyframes loading {
  0% {
    transform: rotate(0);
  }

  50% {
    transform: rotate(160deg);
  }

  100% {
    transform: rotate(360deg);
  }
}
.circle {
  width: 45px;
  height: 45px;
  background-color: transparent;
  border-radius: 50%;
  border: 5px solid #528bee;
  border-left-color: #ccc;

  animation: loading 1s linear 1s infinite;
}
</style>

index.ts

  • (因为我是ts项目所以.ts) 
import { createApp } from "vue";
// 导入写好的Loading.vue文件
import Loading from "./Loading.vue";
export default {
  loading: null,
  /*    每当这个插件被添加到应用程序中时,如果它是一个对象,就会调用 install 方法。
  如果它是一个 function,则函数本身将被调用。在这两种情况下——它都会收到两个参数:由 Vue 的 createApp 生成的 app 对象和用户传入的选项。 */
  install(app) {
    if (this.loading) {
      // 防止多次载入
      app.config.globalProperties.$loading = this.loading;
      return;
    }
    // 创建Loading实例,用于挂载
    let instance = createApp(Loading);
    // 创建div元素装载Loading对象
    let div = document.createElement("div");
    let body = document.body;
    // 导入body中
    body.appendChild(div);
    this.loading = instance.mount(div);
    // 挂载vue身上
    app.config.globalProperties.$loading = this.loading;
  },
};

 在main.ts引入index.ts

// 自定义loading组件
import Loading from "./components/MyLoading/index.ts";

app.use(Loading);

export default app; // 这里导出app的目的,是为了在后面演示js文件中使用插件

封装完成,现在 在请求拦截前和路由跳转前 开启一下全局生效 

 http.js

router.ts

router.beforeEach((to, from, next) => {
  if (to.meta.loading) {
    app.config.globalProperties.$loading.showLoading();
    next();
  } else {
    next();
  }
});
router.afterEach((to, from) => {
  if (to.meta.loading) {
    app.config.globalProperties.$loading.hideLoading();
  }
});

 

封装请求loading完成


 三:封装返回顶部

在src 的components 下新建 俩个文件

 MyBackTop.vue

<template>
  <el-backtop
    style="width: 60px; height: 60px"
    :bottom="50"
    :visibility-height="1000"
  />
</template>

index.ts

import { createApp } from "vue";
import BackTop from "./MyBackTop.vue";
export default {
    BackTop: null,
    install(app) {
        if (this.BackTop) {
            app.config.globalProperties.$BackTop = this.BackTop;
            return;
        }
        let instance = createApp(BackTop);
        let div = document.createElement("div");
        let body = document.body;
        body.appendChild(div);
        this.BackTop = instance.mount(div);
        app.config.globalProperties.$BackTop = this.BackTop;
    },
};

在main.ts引入index.ts

// 自定义回到顶部组件
import BackTop from "./components/MyBackTop/index.ts"

app.use(BackTop);

export default app; // 这里导出app的目的,是为了在后面演示js文件中使用插件

  

结语 

目前为止我们实现了 axios封装 loading 封装 返回顶部封装 !本人亲测保证能用

最后祝大家2022越来越强 

猜你喜欢

转载自blog.csdn.net/m0_57904695/article/details/125891081