如何巧用Vue缓存函数浅析

 更新时间:2021年09月29日 10:46:44   作者:狗胜  
有时候不希望已经请求过的数据,再次请求重复执行刷新操作,我们就需要使用数据缓存,这篇文章主要给大家介绍了关于如何巧用Vue缓存函数的相关资料,需要的朋友可以参考下

vue2中的缓存函数

vue2版本中有这么一个缓存函数

  /**
   * Create a cached version of a pure function.
   */
  function cached (fn) {
    var cache = Object.create(null);
    return (function cachedFn (str) {
      var hit = cache[str];
      return hit || (cache[str] = fn(str))
    })
  }
  

上面这个函数存在一个常用场景,比如存在一个数组,需要把每个元素的首字母转为大写。

const array = ['abc', 'ed', 'abc', 'acd', 'ed', 'fkg', ...];

常用的解决方法

// 定一个capitalize函数
function capitalize (str) {
    return str.charAt(0).toUpperCase() + str.slice(1)
 };
  
 const capitalizeArray = array.map(capitalize);

细心的我们会发现array中存在不少重复的元素, 他们返回的结果一样的,实际不需要重复计算执行capitalize,而且capitalize是一个PURE函数,此时我们可以利用上面的cached做一个备忘录的功能。

改造如下

function capitalize (str) {
    return str.charAt(0).toUpperCase() + str.slice(1)
 };
  
const capitalizeArray = array.map(cached(capitalize));

当遇到重复字符串的时候会直接返回缓存的结果。想想capitalize是一个十分耗时的任务,性能优化不止一点点。

改造vue缓存函数

上面的举例是缓存同步任务的纯函数,在业务开发中存在这么一个场景,输入框搜索。当输入框触发input事件的时候,我们都会调用接口返回查询结果。比如我输入了掘金关键字返回了结果,然后又输入掘金NBA返回了结果,此时我删掉了NBA,又查询掘金, 实际上这个结果我们之前查过,如果缓存起来直接拉缓存即可,不用再去调用接口。

我们基于cached实现一个缓存异步纯函数的备忘录

const cachedAsync = function(fn) {
    const cache = Object.create(null);
    return async str => {
        const hit = cache[str];
        if (hit) {
            return hit;
        }
        // 只缓存成功的Promise, 失败直接重新请求
        return (cache[str] = await fn(str));
    };
};

使用场景

const cachedAsyncQueryPrdList = cachedAsync(prdNo => {
    // 下面是一个请求的操作,返回一个promise
    return queryPrdList({
        prdNo
    });
}); 

<template>
    <el-input v-model="prdNo" placeholder="请输入产品编码" @input="handleQueryPrdList" />
    <el-select>
        <el-option v-for="item in prdList" :label="item.label" :value="item.value">
    </el-select>
</template>
<script>
export default {
    data() {
        prdNo: '',
        prdList: [],
    },
    methods: {
        async handleQueryPrdList() {
            const { data } = await cachedAsyncQueryPrdList(this.prdNo);
            this.prdList = data;
        }
    }
}
</script>

上面实现了,当输入相同的关键字,如果之前请求是成功的,直接拉起缓存,不会重新向服务器发起请求。因为我们的备忘录只会缓存成功的promise。

优化

针对上面的场景,虽然el-input底层已经使用compositionEnd和compositionStart事件来做一层防抖,只有文字真正输入到屏幕上才会去触发input事件。但是这是不够,如果用户输入手速很快,会出现一秒发几次请求的情况,增加了服务器负担。因此这种一般会搭配防抖函数使用。

防抖函数

const debounce = (fn, ms = 300) => {
    let timeoutId;
    return function(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => fn.apply(this, args), ms);
    };
};

然后搭配我们的cachedAsync使用

const cachedAsyncQueryPrdList = cachedAsync(prdNo => {
    // 下面是一个ajax请求的操作,返回一个promise
    return queryPrdList({
        prdNo
    });
}); 

<template>
    <el-input v-model="prdNo" placeholder="请输入产品编码"  @input="debounceQueryPrdListFn" />
    <el-select>
        <el-option v-for="item in prdList" :label="item.label" :value="item.value">
    </el-select>
</template>
<script>
const noop = () => {};
export default {
    data() {
        prdNo: '',
        prdList: [],
        debounceQueryPrdListFn: noop,
    },
    created() {
        this.debounceQueryPrdListFn = debounce(this.handleQueryPrdList);
    },
    methods: {
        async handleQueryPrdList() {
            const { data } = await cachedAsyncQueryPrdList(this.prdNo);
            this.prdList = data;
        }
    }
}
</script>

FBI WARNING:  >>> cachedAsync函数,只适用于PURE函数。

这个实现已经在生产环境稳定使用,大家可以放心食用。

总结

到此这篇关于如何巧用Vue缓存函数的文章就介绍到这了,更多相关巧用Vue缓存函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue使用动态添加路由(router.addRoutes)加载权限侧边栏的方式

    vue使用动态添加路由(router.addRoutes)加载权限侧边栏的方式

    这篇文章主要介绍了vue使用动态添加路由(router.addRoutes)加载权限侧边栏的方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Vue vm.$attrs使用场景详解

    Vue vm.$attrs使用场景详解

    这篇文章主要介绍了vm.$attrs使用场景详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • Vue项目引用百度地图并实现搜索定位等功能(案例分析)

    Vue项目引用百度地图并实现搜索定位等功能(案例分析)

    这篇文章主要介绍了Vue项目引用百度地图并实现搜索定位等功能(案例分析),本篇文章为案例分析,技术点较多,所以篇幅较长,认真阅览的你一定会学到很多知识,需要的朋友可以参考下
    2022-09-09
  • Vue父子组件传值的一些坑

    Vue父子组件传值的一些坑

    这篇文章主要介绍了Vue父子组件传值的一些坑,帮助大家更好的理解和使用vue父子组件,感兴趣的朋友可以了解下
    2020-09-09
  • 多页vue应用的单页面打包方法(内含打包模式的应用)

    多页vue应用的单页面打包方法(内含打包模式的应用)

    这篇文章主要介绍了多页vue应用的单页面打包方法(内含打包模式的应用),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • vue实现移动端图片上传功能

    vue实现移动端图片上传功能

    这篇文章主要为大家详细介绍了vue实现移动端图片上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • 五分钟搞懂Vuex实用知识(小结)

    五分钟搞懂Vuex实用知识(小结)

    本篇文章主要介绍了五分钟搞懂Vuex实用知识,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 在vue上使用cesium开发三维地图的详细过程

    在vue上使用cesium开发三维地图的详细过程

    这篇文章主要给大家介绍了关于在vue上使用cesium开发三维地图的详细过程,Cesium是一个强大的JavaScript库,支持三维地理信息展示,并提供了丰富的地理空间数据可视化功能,需要的朋友可以参考下
    2023-12-12
  • 如何删除vue项目下的node_modules文件夹

    如何删除vue项目下的node_modules文件夹

    这篇文章主要介绍了如何删除vue项目下的node_modules文件夹,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Ant Design Vue Pro静态路由如何改为动态路由

    Ant Design Vue Pro静态路由如何改为动态路由

    这篇文章主要介绍了Ant Design Vue Pro静态路由如何改为动态路由问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10

最新评论