当前位置: 首页 > news >正文

徐州睢宁建设网站网页设计与制作作业成品

徐州睢宁建设网站,网页设计与制作作业成品,网络系统管理大赛样题,美国小卖家做deal网站目录 前言 按钮loading 局部loading 全局loading 前言 loading 的展示和取消可以说是每个前端对接口的时候都要关心的一个问题。这篇文章将要帮你解决的就是如何结合axios更加简洁的处理loading展示与取消的逻辑。 首先在我们平时处理业务的时候loading一般分为三种&#x…

目录

前言

按钮loading

局部loading

全局loading


前言

        loading 的展示和取消可以说是每个前端对接口的时候都要关心的一个问题。这篇文章将要帮你解决的就是如何结合axios更加简洁的处理loading展示与取消的逻辑

        首先在我们平时处理业务的时候loading一般分为三种:按钮loading局部loading,还有全局loading

按钮loading

        其实想写这篇博客的诱因也是因为这个按钮 loading ,在大多数时候我们写按钮 loading 业务的时候是这样写的。

const loading = ref(false)
try {loading.value = trueconst data = await axios.post(`/api/data`)
}
finally {loading.value = false
}

或者这样的写的

const loading = ref(false)
loading.value = true
axios.post(`/api/data`).then(data => {//do something}).finally(() => {loading.value = false})

        可以看到 我们总要处理loading的开始与结束状态。而且好多接口都要这么写。这样太繁琐了,那我们可不可以这样呢?

const loading = ref(false)
const data = await axios.post(`/api/data`,{loading:loading})

把loading的状态给axios统一处理。这样代码是不是就简洁多了呢?处理方式也很简单。

// 请求拦截器
axios.interceptors.request.use(config = >{if (config.loading) {config.loading.value = true}
})
// 响应拦截器
axios.interceptors.response.use(response => {if (response.config.loading) {res.config.loading.value = false}},error => {if (error.config.loading) {config.loading.value = false}}
)

        我们只需要在axios的拦截器中改变loading的值就可以,注意一定要传入一个ref类的值。这种写法也仅适用于vue3。vue2是不行的。

在vue2里面我们可能会想到这样写。

<template><a-button loading="loading.value">保存</a-button>
</template><script>export default {data () {return {loading: { value: false },}},mounted () {const data = await axios.post(`/api/data`,{loading:this.loading})},}
</script>
//拦截器和vue3写法一样

但是很遗憾这样是无法生效的。原因如下

//接口调用
axios.post(接口地址,配置项)
//拦截器
axios.interceptors.request.use(配置项 => {})

        在axios中我们接口调用传入的配置项 和 拦截器返回的配置项 并不是同一个内存地址。axios做了深拷贝处理。所以传入的loading对象和返回的loading对象并不是同一个对象。所以我们在拦截器中修改是完全没有用的。

        可是vue3为什么可以呢?因为 ref 返回的对象是 RefImpl 类的实例,并不是一个普通的对象,axios在做深拷贝的时候没有处理这种实例对象。所以我们就可以从这里出发来改造一下我们的axios写法。代码如下:

axios代码:

const _axios = axios.create({method: `post`,baseURL: process.env.VUE_APP_BASE_URL,
})
//注意:拦截器中比vue3多了个loading!!!
// 请求拦截器
_axios.interceptors.request.use(config = >{if (config.loading) {config.loading.loading.value = true}
})
// 响应拦截器
_axios.interceptors.response.use(response => {if (response.config.loading) {res.config.loading.loading.value = false}},error => {if (error.config.loading) {config.loading.loading.value = false}}
)export const post = (url, params, config) => { if (config?.loading) {class Loading {loading = config.loading}config.loading = new Loading()}return _axios.post(url, params, config)
}

使用方式:

<template><a-button loading="loading.value">保存</a-button>
</template><script>import { post } from '@api/axios'export default {data () {return {//这里的loading可以取任意名字。但是里面必须有valueloading: { value: false },}},mounted () {const data = await post(`/api/data`,{loading:this.loading})},}
</script>

        可以看到实现的原理也很简单。我们在axios里面把出传入的config中的loading对象也变成一个实例对象就好了。在实例对象中记录我们传入的对象,也是以为这里我们会比vue3的写法多一个loading,从而实现响应式。

局部loading

局部loading的添加有两种方式:

  1. ·使用自定义指令 传入true和false 。这样的缺陷是不够灵活,组件内的元素就很难局部添加了,只能全组件添加。值得一提的是,改变true和false的逻辑就可以用我们上述的按钮loading方法。具体的实现方式这里就不再讲述了,如果需要的话可以评论区留言。

  2. ·在axios中封装。每次调用接口的时候传入需要添加loading的dom。接口调用完毕删除dom。实现方法如下。

这里是vue3 + antdV3 技术栈的一个封装。这里用hooks把设置删除loading的逻辑给拆了出去。

axios代码:

const _axios = axios.create({method: `post`,baseURL: import.meta.env.VITE_BASE_URL,
})const { setLoading, deleteLoading } = useAxiosConfig()
// 请求拦截器
_axios.interceptors.request.use(config = >{setLoading(config)
})
// 响应拦截器
_axios.interceptors.response.use(response => {deleteLoading(res.config)},error => {deleteLoading(res.config)}
)export const post = (url, params, config) => { return _axios.post(url, params, config)
}

hooks代码

import { createApp } from 'vue'
import QSpin from '@/components/qSpin/QSpin.vue'
import type { RequestConfig, AxiosError } from '@/types/services/http'
export default function () {/** 使用WeakMap类型的数据 键名所指向的对象可以被垃圾回收 避免dom对象的键名内存泄漏 */const loadingDom = new WeakMap()/*** 添加局部loading* @param config*/const setLoading = (config: RequestConfig) => {const loadingTarget = config.domif (loadingTarget === undefined) returnconst loadingDomInfo = loadingDom.get(loadingTarget)if (loadingDomInfo) {loadingDomInfo.count++} else {const appExample = createApp(QSpin)const loadingExample = appExample.mount(document.createElement(`div`)) as                 InstanceType<typeof QSpin>loadingTarget.appendChild(loadingExample.$el)loadingExample.show(loadingTarget)loadingDom.set(loadingTarget, {count: 1, //记录当前dom的loading次数appExample,})}}/*** 删除局部loading* @param config*/const deleteLoading = (config: RequestConfig) => {const loadingTarget = config.domif (loadingTarget === undefined) returnconst loadingDomInfo = loadingDom.get(loadingTarget)if (loadingDomInfo) {if (--loadingDomInfo.count === 0) {loadingDom.delete(loadingTarget)loadingDomInfo.appExample.unmount()}}}return { setLoading, deleteLoading }
}

        基础逻辑,很简单。只需要接口请求的时候的添加loading ,接口响应完成的时候删除loading。但是随之而来的就有一个问题,如果多个接口同时请求 或者 一个接口频繁请求需要覆盖的都是同一个dom,这样我们添加的loading就会有很多个相同的,相互覆盖。因此上述代码定义了一个loadingDom 记录当前正在loading的dom有哪些,如果有一样的进来的 就把count加一 ,结束后就把count减一。如果count为零则删除loading。

使用实例代码:

<template><div><div ref="head_dom">我是头部数据</div><a-card ref="card_dom">我是卡片内容</a-card></div>
</template><script setup lang="ts">import { post } from '@api/axios'import { ref, onMounted } from 'vue'const head_dom = ref()const card_dom = ref()//这边写了两个是为了演示下 直接在html标签上面绑定ref拿到的就是dom。在组件上面拿到的是组件实例要$el一下onMounted(async () => {const data1 = await post(`/api/head`, { dom: head_dom.value })const data2 = await post(`/api/card`, { dom: card_dom.value.$el })})
</script>

下面简单解释下hooks代码中QSpin组件的代码。

<template><div v-show="visible" class="q-spin"><spin tip="加载中" /></div>
</template><script setup lang="ts">import { Spin } from 'ant-design-vue'import { ref } from 'vue'const visible = ref(false)const show = (dom: HTMLElement) => {visible.value = truedom.style.transform = dom.style.transform || `translate(0)`}defineExpose({ show })
</script><style scoped lang="less">.q-spin {position: fixed;z-index: 999;top: 0;bottom: 0;left: 0;right: 0;display: flex;flex-direction: column;justify-content: center;align-items: center;background-color: rgb(0 0 0 / 10%);}
</style>

        这里是对antdv3的Spin组件做了一个简单的二次封装。主要讲解的就是一个loading覆盖传入dom的方法。

        大多数地方使用的方式都是 relative 和 absolute 定位组合的方式,但是这里采用了transform 和 fixed定位组合的方式。因为我们的项目中可能出现这样一种情况

  <div style="position: relative"><div ref="div_dom"><div style="position: absolute">我是内容</div></div></div>

        假如 我们要给中间的的div添加loading, 使用relative 和 absolute 定位组合的方式。那么中间的div就会在样式表种添加一个position: relative的属性,这样代码就会变成这样

  <div style="position: relative"><div style="position: relative" ref="div_dom"><div style="position: absolute">我是内容</div></div></div>

        很明显 我们第三层div定位的根节点就从第一层变成了第二层,这样就会有可能导致我们样式的错乱。因此笔者采用了transform 和 fixed定位组合的方式。虽然上述的情况可能还会出现 但是会大大减少出现的可能性。

全局loading

        这个就很简单了。如果你封装好了局部的loading 直接在配置项的dom中传入document.body 即可!

http://www.hkea.cn/news/711400/

相关文章:

  • 苏州乡村旅游网站建设策划书网站建设百度推广
  • 12380网站建设情况总结百度浏览器入口
  • 直播网站开发要多久排行榜前十名
  • 网站备案完才能建站吗企业建站公司
  • 网站开发外包合同西安网站优化公司
  • 2022网页设计尺寸规范和要求怎么做seo关键词优化
  • 北京大学两学一做网站十大收益最好的自媒体平台
  • 网站开发服务费企业网站建设的一般要素
  • 台州企业网站制作公司郴州网站推广
  • 如何做移动端网站邮件营销
  • 网站制作佛山crm管理系统
  • 网站综合营销方案设计网页设计教程
  • 东莞做网站制作宁波技术好的企业网站制作
  • 广州做网站公司哪家好如何注册一个网站
  • 网站备案协议书互联网营销师证书含金量
  • 广州企业网站建设报价免费推广网站大全
  • 宁波网站排名怎么提交网址让百度收录
  • 杭州 手机网站建设活动营销
  • 加网络网站建设工作室做一个企业网站大概需要多少钱
  • 张家港优化网站seo百度网盘下载
  • 烟台有没有做网站网站安全
  • 网站建设与制作设计公司惠州seo代理商
  • 东营新闻网今日头条常州网站seo
  • 东莞全网合一网站黄页引流推广网站软件免费
  • wordpress的数据库在那里百度seo如何快速排名
  • wordpress手机客服代码免费seo快速排名工具
  • web网站开发作品关键词歌词图片
  • 汕头行业网站seo培训公司
  • 网站背景图片优化关键词歌曲免费听
  • 郑州做网站哪家专业我要发布信息