教你如何在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来解决问题。

相关推荐
看到我请叫我铁锤2 小时前
vue3中THINGJS初始化步骤
前端·javascript·vue.js·3d
谢尔登3 小时前
defineProperty如何弥补数组响应式不足的缺陷
前端·javascript·vue.js
涔溪4 小时前
实现将 Vue2 子应用通过无界(Wujie)微前端框架接入到 Vue3 主应用中(即 Vue3 主应用集成 Vue2 子应用)
vue.js·微前端·wujie
T***u3335 小时前
前端框架在性能优化中的实践
javascript·vue.js·前端框架
jingling5556 小时前
vue | 在 Vue 3 项目中集成高德地图(AMap)
前端·javascript·vue.js
油丶酸萝卜别吃6 小时前
Vue3 中如何在 setup 语法糖下,通过 Layer 弹窗组件弹出自定义 Vue 组件?
前端·vue.js·arcgis
J***Q29212 小时前
Vue数据可视化
前端·vue.js·信息可视化
JIngJaneIL13 小时前
社区互助|社区交易|基于springboot+vue的社区互助交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·社区互助
ttod_qzstudio14 小时前
深入理解 Vue 3 的 h 函数:构建动态 UI 的利器
前端·vue.js
1***s63214 小时前
Vue图像处理开发
javascript·vue.js·ecmascript