如何巧用Vue缓存函数浅析

目录
  • vue2中的缓存函数
  • 改造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缓存函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 关于Vue实现组件信息的缓存问题

    当我们在开发vue的项目过程中,避免不了在路由切换到其他component再返回后该组件数据会重新加载,处理这种情况我们就需要用到keep-alive来缓存vue的组件信息,使其不再重新加载. 在app.vue里 <keep-alive> <router-view></router-view> </keep-alive> 但是这种情况会对所有的组件进行缓存,不能达到单个组件缓存的效果. 那么我们给部分组件加上,实现方法如下: 在app.vue里 <!-

  • vue项目中实现缓存的最佳方案详解

    需求 在开发vue的项目中有遇到了这样一个需求:一个视频列表页面,展示视频名称和是否收藏,点击进去某一项观看,可以收藏或者取消收藏,返回的时候需要记住列表页面的页码等状态,同时这条视频的收藏状态也需要更新, 但是从其他页面进来视频列表页面的时候不缓存这个页面,也就是进入的时候是视频列表页面的第一页 一句话总结一下: pageAList->pageADetail->pageAList, 缓存pageAList, 同时该视频的收藏状态如果发生变化需要更新, 其他页面->pageAList,

  • 详解Vue中组件的缓存

    之前在<Vue一个案例引发的动态组件与全局事件绑定总结>这篇文章中简单提到过组件的缓存.当时只是简单的提供了一个解决问题的思路,并没有说到多少组件缓存的东西,今天我们就来详细说说组件的缓存. 组件化开发模式下,我们会把整个项目拆分成很多组件,然后按照合理的方式组织起来. 自然就存在组件之间的切换问题,Vue 中有个「动态组件」的概念,它能够让我们更好的实现组件的切换. 在实际的项目开发中,产品是不可能放过我们的,需求总是在不停的变化,如果你碰到那些不改需求的产品就嫁了吧,太难得了. 最近项目中

  • vue项目强制清除页面缓存的例子

    异常描述: 支付宝中内嵌h5项目(vue框架开发),前端重新打包上传之后访问页面会导致页面空白.页面tab点击异常之类异常情况,需要手动清除支付宝缓存才可以正常访问. 解决方案: 在HTTP协议中,只有后端返回 expires 或 Cache-Control:max-age=XXX, 前端才缓存. 但在浏览器中,默认会对 html css js 等静态文件.以及重定向进行缓存,如果在HEAD头中指定: <HEAD> <METAHTTP-EQUIV="Pragma"CO

  • 关于vue里页面的缓存详解

    keep-alive是vue内置的一个组件,可以使被它包含的组件处于保留状态,或避免被重新渲染. 用法: 运行结果描述: input输入框内,路由切换输入框内部的内容不会发生改变. 在keep-alive标签内部添加 include:字符串或正则表达式.只有匹配的组件会被缓存 exclude: 字符串或正则表达式.任何匹配的组件都不会被缓存. 结合router缓存部分页面: 比较实用的例子: 思路:通过beforeRouterLeave这个钩子来对路由里面的keepAlive进行赋值.从而动态的

  • 如何巧用Vue缓存函数浅析

    目录 vue2中的缓存函数 改造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] =

  • vue缓存之keep-alive的理解和应用详解

    官方解释: <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们.和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中. 当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行. 主要用于保留组件状态或避免重新渲染. keep-alive 是 Vue 的内置组件,

  • 如何巧用Vue.extend继承组件实现el-table双击可编辑(不使用v-if、v-else)

    目录 问题描述 效果图 代码思路 代码思路中的三个问题解答 问题一:如何创建一个el-input标签? 问题二三:el-input标签和span标签的来回替换恢复 完整代码 目录结构 用于继承的el-input组件 用于继承的span组件 统一继承并暴露data.js文件 使用继承的three.vue组件 总结 问题描述 有一个简单的表格,产品要求实现双击可编辑 看了一下网上的帖子,大多数都是搞两部分dom,一块是输入框,用于编辑状态填写:另一块是普通标签,用于在不编辑显示状态下呈现单元格文字内

  • Vue reactive函数实现流程详解

    目录 1.Reflect 2.Proxy的工作原理 3.代理Object 4.合理的触发响应 5.深响应和浅响应 6.只读和浅只读 7.代理数组 1.Reflect   Proxy有着可以拦截对对象各种操作的能力,比如最基本的get和set操作,而Reflect也有与这些操作同名的方法,像Reflect.set().Reflect.get(),这些方法和它们所对应的对象基本操作完全一致. const data = { value: '1', get fn() { console.log(this

  • Vue渲染函数详解

    前面的话 Vue 推荐在绝大多数情况下使用 template 来创建HTML.然而在一些场景中,真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器.本文将详细介绍Vue渲染函数 引入 下面是一个例子,如果要实现类似下面的效果.其中,H标签可替换 <h1> <a name="hello-world" href="#hello-world" rel="external nofol

  • 深入理解vue Render函数

    最近在学习vue,正好今日留个笔记,我自己还在摸索学习中,现整理出来以作记录. 会使用基本的Render函数后,就会想,这怎么用 v-for/v-if/v-model;我写个vue Render函数进阶 首先是v-if 的转化使用全局组件的v 值决定组件渲染的状态,对实例中传递的props的"nnum"值得控制可以自如的切换两种状态显示.这样就是和v-if 一样使用组件了 <div id="app"> <mycom :v="nnum&qu

  • python 中的divmod数字处理函数浅析

    divmod(a,b)函数 中文说明: divmod(a,b)方法返回的是a//b(除法取整)以及a对b的余数 返回结果类型为tuple 参数: a,b可以为数字(包括复数) 版本: 在python2.3版本之前不允许处理复数,这个大家要注意一下 英文说明: Take two (non complex) numbers as arguments and return a pair of numbers consisting of their quotient and remainder when

  • python遍历序列enumerate函数浅析

    enumerate函数用于遍历序列中的元素以及它们的下标. enumerate函数说明: 函数原型:enumerate(sequence, [start=0]) 功能:将可循环序列sequence以start开始分别列出序列数据和数据下标 即对一个可遍历的数据对象(如列表.元组或字符串),enumerate会将该数据对象组合为一个索引序列,同时列出数据和数据下标. 举例说明: 存在一个sequence,对其使用enumerate将会得到如下结果: start        sequence[0]

  • 对vue里函数的调用顺序介绍

    method用来定义方法的,比如你@click="test",methods就定义test这个方法 created和ready都是 vue 组件的生命周期 created 类型: Function 详细: 在实例创建之后同步调用.此时实例已经结束解析选项,这意味着已建立:数据绑定,计算属性,方法,watcher/事件回调.但是还没有开始 DOM 编译,$el 还不存在. ready 类型: Function 详细: 在编译结束和 el第一次插入文档之后调用,如在第一次attached钩

  • vue缓存的keepalive页面刷新数据的方法

    用到这个的业务场景是这样的: a页面点击新建列表按钮进入到新建的页面b,填写b页面并点击b页面确认添加按钮,把这些数据带到a页面,填充到列表(数组),可以添加多条, 点击这条的时候进入到编辑页面,确认修改之后,回退到a页面,a页面需要更新这条数据 实现这个功能的时候,由于是路由页面之间的跳转,首先想到的方案有几个:1. 用sessionStorage本地存储:2. 用路由参数带过去:3. 用兄弟组件传值 由于是添加完之后如果按回退是需要退出整个页面,如果用路由跳转,会出现回退到编辑页面了,所以这

随机推荐