教你如何在vue项目中使用‘useState’并添加额外的魔法

教你如何在vue项目中使用'useState'并添加额外的魔法

用法一览

javascript 复制代码
import useLoading from '@/useHooks/useLoading.js';
const [loading, setLoading] = useLoading();
setLoading(true) //setLoading(false)

起源

这种奇奇怪怪的代码背后总会有一个奇奇怪怪的需求。某天产品经理找到我说:小王啊,我发现我们公司平台的页面按钮的加载状态就是闪一下,动画都没展示完就结束了,用户体验不是很好啊。

此时我内心的OS是:接口请求太快了也能怪我吗。但是毕竟是吩咐下来的任务,该完成还是要完成的而且这个需求看起来好像也并不是很复杂啊,那就整。

需求分析

产品说按钮的加载状态太快,那直接原因就是接口返回的速度太快了,当然我们不能减缓网络请求的速度,那么就只有一种办法,延长我们 loading 为 true 的时间。那么就出现了最粗暴的办法。

javascript 复制代码
import { ref } from 'vue'
const loading = ref(false)
const fn = async ()=>{
    loading.value = true;
    const {data,code} = await xxx()
    setTimeout(()=>{loading.value = false},1000)
}
fn()

当然这个方法有个致命的问题,就是如果xxx 请求返回的时间也很慢,那这个延迟修改加载状态无疑是雪上加霜了,直接导致体验负优化,那么我们要做的就是给loading状态加上一个兜底。即:当loading时间小于某个值的时候 loading状态并不会变化,只有超过某个时间值的时候我们才允许loading状态的改变。有了目标,那就开始想怎么实现。

首先,我们要有一个值去记录是否达到我们的兜底时间,而且从实现上来说我们只用考虑loading状态从false变为true的中间的时间。

其次还要有一个值记录真实的状态,即异步操作结束的状态。

最后就是我们的综合loading状态依赖于这两个状态,有一个还在加载那么就还在加载。

功能实现

直接上代码:

javascript 复制代码
// useLoading.js
import { ref, computed } from 'vue';
​
/**
 * @param {number} time 兜底的时间 单位ms
 */
export default (time = 500) => {
    // 变量写入函数内避免数据污染
    const isCounting = ref(false) // 是否在兜底时间
    const isLoading = ref(false) // 真实的加载状态
​
    const countDown = (time) => {
        if (typeof time !== 'number' || isNaN(time)) throw new Error(`expect a [object Number] but got ${isNaN(time) ? 'NaN' : Object.prototype.toString.call(time)}`) // 参数校验
​
        if (isCounting) return // 以防万一
​
        isCounting.value = true // 开始计时
​
        let timer = setTimeout(() => {
            isCounting.value = false // 结束计时
            clearTimeout(timer)
        }, time)
    }
​
    const setLoaing = (val) => {
        isLoading.value = val
        val && countDown(time)
    }
​
    const loading = computed(
        () => isCounting.value || isLoading.value, // 真正loaing中或者没结束倒数时都是loading状态
    )
​
    return [loading, setLoaing]
}

还记得我们开头的用法吗,不记得的同学可以再回去看看,到此这个奇怪的需求就被完美的解决了。

写在最后

其实写这篇文章的目的也并不是说我实现了一个怎么样的功能,更重要的是解决问题的思路,当然有思路也要有相应的直觉或者叫灵感才能写的出优秀的代码(此处并不是自夸,笔者写代码的时候也是推翻重来了好多次。)

当然解决思路也并不只有这一种,此处我再抛砖引玉一下 :其实可以从v-loading这个自定义指令入手或者对el-button进行二次封装,笔者用的vue2.7版本,element-ui 中业务组件还是使用的optionAPI 故可以使用extends来解决问题。

相关推荐
别拿曾经看以后~17 分钟前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
Devil枫7 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
GIS程序媛—椰子8 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
毕业设计制作和分享8 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果9 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄9 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
凉辰10 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
薛一半12 小时前
PC端查看历史消息,鼠标向上滚动加载数据时页面停留在上次查看的位置
前端·javascript·vue.js
MarcoPage12 小时前
第十九课 Vue组件中的方法
前端·javascript·vue.js