Vue中keep-alive 实现后退不刷新并保持滚动位置


Posted in Javascript onMarch 17, 2020

什么是KeepAlive?

首先,我们要明确我们谈的是TCP的 KeepAlive 还是HTTP的 Keep-Alive。TCP的KeepAlive和HTTP的Keep-Alive是完全不同的概念,不能混为一谈。实际上HTTP的KeepAlive写法是Keep-Alive,跟TCP的KeepAlive写法上也有不同。

  • TCP的keepalive是侧重在保持客户端和服务端的连接,一方会不定期发送心跳包给另一方,当一方端掉的时候,没有断掉的定时发送几次心跳包,如果间隔发送几次,对方都返回的是RST,而不是ACK,那么就释放当前链接。设想一下,如果tcp层没有keepalive的机制,一旦一方断开连接却没有发送FIN给另外一方的话,那么另外一方会一直以为这个连接还是存活的,几天,几月。那么这对服务器资源的影响是很大的。
  • HTTP的keep-alive一般我们都会带上中间的横杠,普通的http连接是客户端连接上服务端,然后结束请求后,由客户端或者服务端进行http连接的关闭。下次再发送请求的时候,客户端再发起一个连接,传送数据,关闭连接。这么个流程反复。但是一旦客户端发送connection:keep-alive头给服务端,且服务端也接受这个keep-alive的话,两边对上暗号,这个连接就可以复用了,一个http处理完之后,另外一个http数据直接从这个连接走了。减少新建和断开TCP连接的消耗。

二者的作用简单来说:

HTTP协议的Keep-Alive意图在于短时间内连接复用,希望可以短时间内在同一个连接上进行多次请求/响应。

TCP的KeepAlive机制意图在于保活、心跳,检测连接错误。当一个TCP连接两端长时间没有数据传输时(通常默认配置是2小时),发送keepalive探针,探测链接是否存活。

总之,记住HTTP的Keep-Alive和TCP的KeepAlive不是一回事。

tcp的keepalive是在ESTABLISH状态的时候,双方如何检测连接的可用行。而http的keep-alive说的是如何避免进行重复的TCP三次握手和四次挥手的环节。

正文开始。

vue可以通过<keep-alive>元素包裹组件,实现缓存,下次使用时不需要重新创建该组件。但存在一个问题:keep-alive包裹的组件中有滚动元素时,keep-alive不会储存滚动位置。

实现后退不刷新主要依据keep-alive组件的activated和deactivated这两个生命周期钩子函数。

vue钩子函数的执行顺序:

不使用keep-alive

beforeRouteEnter --> created --> mounted --> destroyed

使用keep-alive

初次进入页面,beforeRouteEnter --> created --> mounted --> activated --> deactivated

再次进入缓存的页面,只会触发beforeRouteEnter -->activated --> deactivated。created和mounted不会再执行。

其中,

activated在keep-alive组件激活时调用.

deactivated在keep-alive组件被停用时调用.

Demo 实现了后退不刷新,并且返回时滚动到上次浏览的深度。

该demo中,包含三个链接导航。

home --> pageA --> pageB --> pageC

依次前进,每次前进到一个新页面都需要获取数据,而按下后退键后,

从pageC返回到pageB,pageB不再获取新数据,而是使用之前缓存的数据。

从pageB返回到pageA时,pageA不再获取新数据,而是使用之前的数据。并且当pageA存在滚动条时,返回时会滚动到上次浏览高度。

所以,pageA和pageB需要缓存,pageC不需要缓存。

//router.js
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);

const router = new Router({
 mode: 'hash',
 routes: [
 {
  path: '/',
  name: 'home',
  component: () =>
  import('./views/Home.vue'),
  meta: {
  title: '首页',
  keepAlive: false //此组件不需要被缓存
  }
 },
 {
  path: '/pageA',
  name: 'pageA',
  component: () =>
   import('./views/pageA.vue'),
  meta: {
  title: 'pageA',
  keepAlive: true,
  isBack: false
  }
 },
 {
  path: '/pageB',
  name: 'pageB',
  component: () =>
   import('./views/pageB.vue'),
  meta: {
  title: 'pageB',
  keepAlive: true,
  isBack: false
  }
 },
 {
  path: '/pageC',
  name: 'pageC',
  component: () =>
   import('./views/pageC.vue'),
  meta: {
  title: 'pageC',
  keepAlive: false
  }
 }
 ]
});
export default router;
//pageA.vue
<template>
 <div class="page-a">
  <h1>pageA</h1>
  <div>
   <div class="item" v-for="item in items" @click="goPageB">
    {{ item }}
   </div>
  </div>
  <h1 @click="goPageB">go pageB</h1>
 </div>
</template>

<script>
 export default {
  name: 'PageA',
  data() {
   return {
    msg: "我是PageA页面",
    items: Array.from({length:50}, (v,k) => k),
    data: "",
    scrollTop: 0
   };
  },
  beforeRouteEnter(to, from, next) {
   if(from.name == 'pageB'){
    to.meta.isBack = true;
   }

   next();
  },
  mounted() {
   console.log('mounted....');
   // this指向组件的实例,$el指向当前组件的DOM元素
   const $el = this.$el;
   //滚动事件
   $el.addEventListener("scroll", () => {
    //记录位置
    this.scrollTop = $el.scrollTop;
   });
  },
  activated() {
   if(!this.$route.meta.isBack){
    // 如果isBack是false,表明需要获取新数据,否则就不再请求,直接使用缓存的数据
    this.getData();
   } else {
    //恢复滚动条高度
    if(this.scrollTop) {
     setTimeout(() => {
      this.$el.scrollTop = this.scrollTop;
     }, 100);
    }
   }
   // 恢复成默认的false,避免isBack一直是true
   this.$route.meta.isBack = false;

  },
  methods: {
   getData() {
    // getData方法,模拟从后台请求数据
    this.data = "数据";
    console.log('get data')
   },
   goPageB(){
    this.$router.push({ path: "/pageB" });
   },
   back() {
    this.$router.push({ path: "/" });
   }
  },
 }
</script>
<style>
 .page-a {
  height: 100vh;
  overflow-y: auto;
 }
 .item {
  margin: 5px;
  padding: 10px;
  background: #ccc;
 }
</style>

代码请参考 链接 ;

后退不刷新还可以通过include实现,可参考链接

总结

到此这篇关于Vue中keep-alive 实现后退不刷新并保持滚动位置的文章就介绍到这了,更多相关keep-alive 后退不刷新持滚动位置内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
关于JavaScript中name的意义冲突示例介绍
May 29 Javascript
分享一个自己写的简单的javascript分页组件
Feb 15 Javascript
快速解决Canvas.toDataURL 图片跨域的问题
May 10 Javascript
利用Angularjs和Bootstrap前端开发案例实战
Aug 27 Javascript
vuejs动态组件给子组件传递数据的方法详解
Sep 09 Javascript
jQuery Validate 数组 全部验证问题
Jan 12 Javascript
vue中用H5实现文件上传的方法实例代码
May 27 Javascript
three.js实现3D模型展示的示例代码
Dec 31 Javascript
vue中实现先请求数据再渲染dom分享
Mar 17 Javascript
解决vue-cli + webpack 新建项目出错的问题
Mar 20 Javascript
layer.confirm点击第一个按钮关闭弹出框的方法
Sep 09 Javascript
JavaScript中时间格式化新思路toLocaleString()
Nov 07 Javascript
用js编写留言板
Mar 17 #Javascript
Vue脚手架编写试卷页面功能
Mar 17 #Javascript
基于JavaScript实现留言板功能
Mar 16 #Javascript
JS实现简易留言板(节点操作)
Mar 16 #Javascript
JavaScript实现旋转木马轮播图
Mar 16 #Javascript
基于JavaScript实现贪吃蛇游戏
Mar 16 #Javascript
原生js实现的金山打字小游戏(实例代码详解)
Mar 16 #Javascript
You might like
PHP register_shutdown_function函数的深入解析
2013/06/03 PHP
Laravel 微信小程序后端实现用户登录的示例代码
2019/11/26 PHP
PHP中类与对象功能、用法实例解读
2020/03/27 PHP
JavaScript.The.Good.Parts阅读笔记(二)作用域&amp;闭包&amp;减缓全局空间污染
2010/11/16 Javascript
深入解析JavaScript中的变量作用域
2013/12/06 Javascript
javascript弹出窗口实现代码
2015/11/12 Javascript
跟我学习javascript的垃圾回收机制与内存管理
2015/11/23 Javascript
Javascript中this关键字指向问题的测试与详解
2017/08/11 Javascript
vue 1.0 结合animate.css定义动画效果
2018/07/11 Javascript
vue集成百度UEditor富文本编辑器使用教程
2018/09/21 Javascript
JS页面获取 session 值,作用域和闭包学习笔记
2019/10/16 Javascript
基于element-ui封装可搜索的懒加载tree组件的实现
2020/05/22 Javascript
[13:18]《一刀刀一天》之DOTA全时刻21:详解TI新赛制 A队再露獠牙
2014/06/24 DOTA
[15:15]教你分分钟做大人:狙击手
2014/10/30 DOTA
[01:12]DOTA2 2015年秋季互动指南
2015/11/10 DOTA
python设置windows桌面壁纸的实现代码
2013/01/28 Python
在Python的Flask框架下收发电子邮件的教程
2015/04/21 Python
python查看zip包中文件及大小的方法
2015/07/09 Python
Python下rrdtool模块的基本使用方法
2015/11/13 Python
深入学习python的yield和generator
2016/03/10 Python
使用Python3+PyQT5+Pyserial 实现简单的串口工具方法
2019/02/13 Python
Django实现web端tailf日志文件功能及实例详解
2019/07/28 Python
深入了解python中元类的相关知识
2019/08/29 Python
Python在OpenCV里实现极坐标变换功能
2019/09/02 Python
Pycharm 设置默认解释器路径和编码格式的操作
2021/02/05 Python
HTML5 visibilityState属性详细介绍和使用实例
2014/05/03 HTML / CSS
用HTML5制作视频拼图的教程
2015/05/13 HTML / CSS
德国宠物用品、宠物食品及水族馆网上商店:ZooRoyal
2017/07/09 全球购物
如果Session Bean得Remove方法一直都不被调用会怎么样
2012/07/14 面试题
后勤主管岗位职责
2014/03/01 职场文书
教师教学评估方案
2014/05/09 职场文书
体育教师求职信
2014/05/24 职场文书
2014年心理健康教育工作总结
2014/12/06 职场文书
2015年秋季运动会前导词
2015/07/20 职场文书
七年级之开学家长寄语35句
2019/09/05 职场文书
python+pytest接口自动化之token关联登录的实现
2022/04/06 Python