通过vue提供的keep-alive减少对服务器的请求次数


Posted in Javascript onApril 01, 2018

下面看下通过vue提供的keep-alive减少对服务器的请求次数

VUE2.0中提供了一个keep-alive方法,可以用来缓存组件,避免多次加载相应的组件,减少性能的消耗。比如, 一个页面的数据包括图片、文字等用户都已经加载完了,然后用户通过点击跳转到了另外一个界面。然后从另外一个界面通过返回又回到了原先的界面。如果没有设置的话,那么原先界面的信息就要重新向服务器请求得到。而通过vue提供的keep-alive可以是页面的已经请求的数据得以保存,减少请求的次数,提高用户的体验程度。

        缓存组件又分为两种,缓存整个站点的页面的组件或者缓存部分页面的组件。

         1、缓存所有的页面,适用于每个页面都有请求的情况。方法如下,在需要缓存的router-view用keep-alive标签进行包裹起来。

<keep-alive>
      <router-view></router-view>
     </keep-alive>

              将首次触发请求写到created钩子里边,就能实现缓存。比如从列表页,去了详情页,回来还是原来的页面。

           2、缓存部分组件或者页面,使用router.meta这个属性通过判断的方法可以实现。方法如下:                           

<keep-alive v-if="$route.meta.keepAlive">
      <router-view></router-view>
     </keep-alive>
     <router-view v-if="! $route.meta.keepAlive"></router-view>

                     router设置如下:              

routers:[
        { path: '/home',
          name: home,
          meta:{keepAlive: true}  // 设置为true表示需要缓存,不设置或者false表示不需要缓存          }
          ]

       还可以通过新增的属性include/exclude来设置。见名思意,include包含的意思,exclude除了的意思。这里需要用到组件的名称即name来进行设置,所以name肯定就要加上了。  加入 a,b组件需要缓存,c,d组件不需要缓存。写法如下:

<keep-alive include="a,b">
      <component></component>
     </keep-alive>  
     <keep-alive exclude="c,d">
      <component></component>
     </keep-alive>

 vue项目的优化还可以通过组件的按需加载来实现,就像图片的懒加载一样,如果客户根本就没有看到那些图片,而我们却在打开页面的时候全部给加载完了,这样会大大的增加请求的时间,降低用户的体验程度。懒加载在很多的网站都有用到,比如淘宝、京东等等这样的购物网站,上面的图片链接等等都很多,如果你把滚轴迅速的往下拉的时候,你可能会看到图片加载的情况。

补充:

Vue路由开启keep-alive时的注意点

这个不是业务的要求,但是看到每次进入页面就重新渲染DOM然后再获取数据更新DOM,觉得作为一个前端工程师有必要优化下的加载逻辑,正好vue提供了 keep-alive 的功能,所以就试用了下。当然,干任何事儿都不会一帆风顺的,在路上的磕磕碰碰在所难免,故在此记录下遇到的问题,希望看到这篇文章的人能有所帮助。ps:这个也没多难。

HTML部分:

<template>
 <div class="app">
 <keep-alive>
  <router-view></router-view>
 </keep-alive>
 </div>
</template>JavaScript部分:
.....
 created: function () {
  console.log(1)
 },
 mounted: function () {
  console.log(2)
 },
 activated: function () {
  console.log(3)
 },
 deactivated: function () {
  console.log(4)
 }

.....1. 什么阶段获取数据

页面生命周期钩子如上面的代码所示,这四个是最常用到的部分。这部分需要注意下,当引入keep-alive 的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。

我们知道 keep-alive 之后页面模板第一次初始化解析变成HTML片段后,再次进入就不在重新解析而是读取内存中的数据,即,只有当数据变化时,才使用VirtualDOM进行diff更新。故,页面进入的数据获取应该在activated中也放一份。数据下载完毕手动操作DOM的部分也应该在activated中执行才会生效。

所以,应该activated中留一份数据获取的代码,或者不要created部分,直接将created中的代码转移到activated中。

2. $route 中的数据读不到

以前的写法是在data中将需要的 $route 数据进行赋值,便于其余方法使用,但是使用了 keep-alive 后数据需要进入页面在activated中再次获取,才能达到更新的目的。定义一个initData方法,然后在activated中启动。

initData: function () {
  let _this = this;
  _this.fromLocation = JSON.parse(this.$route.query.fromLocation);
  _this.toLocation = JSON.parse(this.$route.query.toLocation);
  _this.activeIndex = parseInt(this.$route.params.activeIndex) || 0;
  _this.policyType = parseInt(this.$route.params.policyType) || 0;
  },

      3. 当页动态修改url

需求描述:当页面在进行轮播操作的时候希望能记录当前显示的轮播ID(activeIndex)。当进入下一个页面再返回的时候能记住之前的选择,将轮播打到之前的ID位置。所以我想将这部分信息固化在url中,轮播发生变化时,修改URL。这样实现比较符最小修改原则,其余页面不用变动。

之前的写法是将activeIndex放在 $route 的query中,当轮播后,将

activeIndex的值存入 $route.query.activeIndex 中,然后 $router.replace 当前路由,理论上应该能发生变化,但实际没有。

查看文档后说, $route 是只读模式。当然,对象部分是他监管不到的,我修改了并不是正统的做法。

神奇的地方来了:当我将activeIndex记在params中,轮播变动修改params中的参数,然后 $router.replace 当前路由,却能发生对应的变化。代码如下:

let swiperInstance = new Swiper('#swiper', {
 pagination: '.swiper-pagination',
 paginationClickable: false,
 initialSlide: activeIndex,
 onSlideChangeEnd: function (swiper) {
  let _activeIndex = swiper.activeIndex;
  _this.$route.params.activeIndex = _activeIndex;
  // $router我放到了window上方便调用
  window.$router.replace({
   name: _this.$route.name,
   params: _this.$route.params,
   query: _this.$route.query
  });
  // 根据activeIndex,在这里初始化下面显示的数据
  _this.transferDetail = _this.allData.plans[_activeIndex].segments;
  _this.clearBusDetailFoldState();
 }
});

4. 事件如何处理

估计你也能猜到,发生的问题是事件绑定了很多次,比如上传点击input监听change事件,突然显示了多张相同图片的问题。

也就是说,DOM在编译后就缓存在内容中了,如果再次进入还再进行事件绑定初始化则就会发生这个问题。

解决办法:在mounted中绑定事件,因为这个只执行一次,并且DOM已准备好。如果插件绑定后还要再执行一下事件的handler函数的话,那就提取出来,放在activated中执行。比如:根据输入内容自动增长textarea的高度,这部分需要监听textarea的input和change事件,并且页面进入后还要再次执行一次handler函数,更新textarea高度(避免上次输入的影响)。

5. 地图组件处理

想必这是使用 keep-alive 最直接的性能表现。之前是进入地图页面后进行地图渲染+线路标记;现在是清除以前的线路标记绘制新的线路,性能优化可想而知!

我这里使用的是高德地图,在mounted中初始化map,代码示例如下:

export default {
 name: 'transferMap',
 data: function () {
  return {
   map: null,
  }
 },
 methods: {
  initData: function () {},
  searchTransfer: function (type) {},
  // 地图渲染 这个在transfer-map.html中使用
  renderTransferMap: function (transferMap) {}
 },
 mounted: function () {
  this.map = new AMap.Map("container", {
   showBuildingBlock: true,
   animateEnable: true,
   resizeEnable: true,
   zoom: 12 //地图显示的缩放级别
  });
 },
 activated: function () {
  let _this = this;
  _this.initData();
  // 设置title
  setDocumentTitle('换乘地图');
  _this.searchTransfer(_this.policyType).then(function (result) {
   // 数据加载完成
   // 换乘地图页面
   let transferMap = result.plans[_this.activeIndex];
   transferMap.origin = result.origin;
   transferMap.destination = result.destination;
   // 填数据
   _this.transferMap = transferMap;
   // 地图渲染
   _this.renderTransferMap(transferMap);
  });
 },
 deactivated: function () {
  // 清理地图之前的标记
  this.map.clearMap();
 },
}

6. document.title修改

这个不是 keep-alive 的问题,不过我也在这里分享下。

问题是,使用下面这段方法,可以修改Title,但是页面来回切换多次后就不生效了,我也不知道为啥,放到setTimeout中就直接不执行。

document.title = '页面名称';下面是使用2种环境的修复方法:

纯js实现

function setDocumentTitle(title) {
 "use strict";
 //以下代码可以解决以上问题,不依赖jq
 setTimeout(function () {
  //利用iframe的onload事件刷新页面
  document.title = title;
  var iframe = document.createElement('iframe');
  iframe.src = '/favicon.ico'; // 必须
  iframe.style.visibility = 'hidden';
  iframe.style.width = '1px';
  iframe.style.height = '1px';
  iframe.onload = function () {
   setTimeout(function () {
    document.body.removeChild(iframe);
   }, 0);
  };
  document.body.appendChild(iframe);
 }, 0);
}

jQuery/Zepto实现

function setDocumentTitle(title) {
 //需要jQuery
 var $body = $('body');
 document.title = title;
 // hack在微信等webview中无法修改document.title的情况
 var $iframe = $('<iframe src="/favicon.ico"></iframe>');
 $iframe.on('load', function () {
  setTimeout(function () {
   $iframe.off('load').remove();
  }, 0);
 }).appendTo($body);
}

总结

以上所述是小编给大家介绍的通过vue提供的keep-alive减少对服务器的请求次数,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
JavaScript中Object和Function的关系小结
Sep 26 Javascript
jquery sortable的拖动方法示例详解
Jan 16 Javascript
jQuery添加和删除输入文本框标签代码
May 20 Javascript
jQuery短信验证倒计时功能实现方法详解
May 25 Javascript
自动化测试读写64位操作系统的注册表
Aug 15 Javascript
Node.js用readline模块实现输入输出
Dec 16 Javascript
解决Mac node版本升级失败的问题
May 16 Javascript
详解如何在你的Vue项目配置vux
Jun 04 Javascript
BootStrap表单验证中的非Submit类型按钮点击时触发验证的坑
Sep 05 Javascript
你可能从未使用过的11+个JavaScript特性(小结)
Jan 08 Javascript
jquery实现有过渡效果的tab切换
Jul 17 jQuery
vuex中遇到的坑,vuex数据改变,组件中页面不渲染操作
Nov 16 Javascript
vue-cli项目优化方法- 缩短首屏加载时间
Apr 01 #Javascript
vuejs项目打包之后的首屏加载优化及打包之后出现的问题
Apr 01 #Javascript
Vue项目使用CDN优化首屏加载问题
Apr 01 #Javascript
对Angular中单向数据流的深入理解
Mar 31 #Javascript
jQuery中复合选择器简单用法示例
Mar 31 #jQuery
jQuery中内容过滤器简单用法示例
Mar 31 #jQuery
jQuery中可见性过滤器简单用法示例
Mar 31 #jQuery
You might like
php+ajax 文件上传代码实例
2019/03/18 PHP
PHP+redis实现微博的拉模型案例详解
2019/07/10 PHP
js或css文件后面跟参数的原因说明
2010/01/09 Javascript
js 键盘记录实现(兼容FireFox和IE)
2010/02/07 Javascript
Extjs Gird 支持中文拼音排序实现代码
2013/04/15 Javascript
JQuery弹出炫丽对话框的同时让背景变灰色
2014/05/22 Javascript
js中this用法实例详解
2015/05/05 Javascript
asp.net中oracle 存储过程(图文)
2015/08/12 Javascript
使用基于Node.js的构建工具Grunt来发布ASP.NET MVC项目
2016/02/15 Javascript
js判断复选框是否选中及选中个数的实现代码
2016/05/30 Javascript
Ajax+FormData+javascript实现无刷新表单信息提交
2016/10/24 Javascript
three.js实现围绕某物体旋转
2017/01/25 Javascript
微信小程序 本地数据读取实例
2017/04/27 Javascript
js实现日期显示的一些操作(实例讲解)
2017/07/27 Javascript
Cocos2d实现刮刮卡效果
2018/12/20 Javascript
[09:23]国际邀请赛采访专栏:iG战队VK,Tongfu战队Cu
2013/08/05 DOTA
[01:19:33]DOTA2-DPC中国联赛 正赛 iG vs VG BO3 第一场 2月2日
2021/03/11 DOTA
Python实现简单拆分PDF文件的方法
2015/07/30 Python
举例讲解Python设计模式编程中的访问者与观察者模式
2016/01/26 Python
完美解决python遍历删除字典里值为空的元素报错问题
2016/09/11 Python
python中numpy基础学习及进行数组和矢量计算
2017/02/12 Python
apache部署python程序出现503错误的解决方法
2017/07/24 Python
Python基于回溯法子集树模板解决最佳作业调度问题示例
2017/09/08 Python
python删除过期log文件操作实例解析
2018/01/31 Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
2019/08/10 Python
DataFrame 数据合并实现(merge,join,concat)
2020/06/14 Python
详解python命令提示符窗口下如何运行python脚本
2020/09/11 Python
某公司C#程序员面试题笔试题
2014/05/26 面试题
施工工地安全标语
2014/06/07 职场文书
小学生感恩老师演讲稿
2014/08/28 职场文书
热情服务标语
2014/10/07 职场文书
出纳工作检讨书
2014/10/18 职场文书
2015毕业实习推荐信
2015/03/23 职场文书
2015新生加入学生会自荐书
2015/03/24 职场文书
解决pytorch读取自制数据集出现过的问题
2021/05/31 Python
Java设计模式之代理模式
2022/04/22 Java/Android