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

相关推荐
学习路上的小刘5 分钟前
vue h5 蓝牙连接 webBluetooth API
前端·javascript·vue.js
&白帝&5 分钟前
vue3常用的组件间通信
前端·javascript·vue.js
冯宝宝^1 小时前
基于mongodb+flask(Python)+vue的实验室器材管理系统
vue.js·python·flask
cc蒲公英2 小时前
Vue2+vue-office/excel 实现在线加载Excel文件预览
前端·vue.js·excel
森叶2 小时前
Electron-vue asar 局部打包优化处理方案——绕开每次npm run build 超级慢的打包问题
vue.js·electron·npm
小小竹子3 小时前
前端vue-实现富文本组件
前端·vue.js·富文本
青稞儿3 小时前
面试题高频之token无感刷新(vue3+node.js)
vue.js·node.js
程序员凡尘4 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js
Bug缔造者10 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_10 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js