浅谈Angular路由复用策略


Posted in Javascript onOctober 04, 2017

一、引言

路由在执行过程中对组件无状态操作,即路由离退时组件状态也一并被删除;当然在绝大多数场景下这是合理的。

但有时一些特殊需求会让人半死亡状态,当然这一切都是为了用户体验;一种非常常见场景,在移动端中用户通过关键词搜索商品,而死不死的这样的列表通常都会是自动下一页动作,此时用户好不容易滚动到第二页并找到想要看的商品时,路由至商品详情页,然后一个后退……用户懵逼了。

Angular路由与组件一开始就透过 RouterModule.forRoot 形成一种关系,当路由命中时利用ComponentFactoryResolver 构建组件,这是路由的本质。

而每一个路由并不一定是一次性消费,Angular 利用 RouteReuseStrategy 贯穿路由状态并决定构建组件的方式;当然默认情况下(DefaultRouteReuseStrategy)像开头说的,一切都不进行任何处理。

RouteReuseStrategy 从2就已经是实验性,当前依然如此,这么久应该是可信任。

二、RouteReuseStrategy

RouteReuseStrategy 我称它为:路由复用策略;并不复杂,提供了几种办法通俗易懂的方法:

  • shouldDetach 是否允许复用路由
  • store 当路由离开时会触发,存储路由
  • shouldAttach 是否允许还原路由
  • retrieve 获取存储路由
  • shouldReuseRoute 进入路由触发,是否同一路由时复用路由

这看起来就像是一个时间轴关系,用一种白话文像是这样:把路由 /list 设置为允许复用(shouldDetach),然后将路由快照存在 store 当中;当 shouldReuseRoute 成立时即:再次遇到 /list 路由后表示需要复用路由,先判断 shouldAttach 是否允许还原,最后从 retrieve 拿到路由快照并构建组件。

当理解这一原理时,假如我们拿开头搜索列表返回的问题就变得非常容易解决。

三、一个示例

诚如上面说明的,只需要实现 RouteReuseStrategy 接口即可自定义一个路由利用策略。

1、创建策略

import {RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle} from '@angular/router';

export class SimpleReuseStrategy implements RouteReuseStrategy {

  _cacheRouters: { [key: string]: any } = {};

  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return true;
  }
  store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    this._cacheRouters[route.routeConfig.path] = {
      snapshot: route,
      handle: handle
    };
  }
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return !!this._cacheRouters[route.routeConfig.path];
  }
  retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    return this._cacheRouters[route.routeConfig.path].handle;
  }
  shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    return future.routeConfig === curr.routeConfig;
  }
}

定义一个 _cacheRouters 用于缓存数据(路由快照及当前组件实例对象)。

  • shouldDetach 直接返回 true 表示对所有路由允许复用
  • store 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象;path等同RouterModule.forRoot中的配置。
  • shouldAttach 若 path 在缓存中有的都认为允许还原路由
  • retrieve 从缓存中获取快照,若无则返回null
  • shouldReuseRoute 进入路由触发,判断是否同一路由

2、注册

最后将策略注册到模块当中:

providers: [
 { provide: RouteReuseStrategy, useClass: SimpleReuseStrategy }
]

假设我们有这么一个路由配置:

RouterModule.forRoot([
 { path: 'search', component: SearchComponent },
 { path: 'edit/:id', component: EditComponent }
])

搜索组件用于搜索动作,并在根据搜索结果跳转至编辑页,保存后又回到最后搜索结果的状态(这部分代码我就不贴有兴趣见 plnkr)。

四、结论

上述只是一个简单的抛砖引玉作用,实则对于复用的判断会更复杂、滚动条位置、缓存清理等等。

善用这种路由复用策略机制可以解决很多Web体验上的问题。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jquery的大众点评,分类导航实现代码
Aug 23 Javascript
THREE.JS入门教程(1)THREE.JS使用前了解
Jan 24 Javascript
关于jquery中全局函数each使用介绍
Dec 10 Javascript
使用jquery prev()方法找到同级的前一个元素
Jul 11 Javascript
让javascript加载速度倍增的方法(解决JS加载速度慢的问题)
Dec 12 Javascript
js实现显示当前状态的导航效果代码
Aug 28 Javascript
基于replaceChild制作简单的吞噬特效
Sep 21 Javascript
详解原生JavaScript实现jQuery中AJAX处理的方法
May 10 Javascript
javascript 初学教程及五子棋小程序的简单实现
Jul 04 Javascript
JQuery特殊效果和链式调用操作示例
May 13 jQuery
layui的数据表格+springmvc实现搜索功能的例子
Sep 28 Javascript
jquery+ajax实现异步上传文件显示进度条
Aug 17 jQuery
React-Native之定时器Timer的实现代码
Oct 04 #Javascript
vuejs使用$emit和$on进行组件之间的传值的示例
Oct 04 #Javascript
无限循环轮播图之运动框架(原生JS实现)
Oct 01 #Javascript
原生JS实现图片无缝滚动方法(附带封装的运动框架)
Oct 01 #Javascript
原生js封装运动框架的示例讲解
Oct 01 #Javascript
JS Testing Properties 判断属性是否在对象里的方法
Oct 01 #Javascript
基于原生js运动方式关键点的总结(推荐)
Oct 01 #Javascript
You might like
YB217、YB235、YB400浅听
2021/03/02 无线电
Windows下安装Memcached的步骤说明
2010/04/25 PHP
php foreach 参数强制类型转换的问题
2010/12/10 PHP
php 判断数组是几维数组
2013/03/20 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
2014/06/23 PHP
PHP面向对象自动加载机制原理与用法分析
2016/10/14 PHP
js操作时间(年-月-日 时-分-秒 星期几)
2010/06/20 Javascript
jquery的map与get方法详解
2013/11/04 Javascript
js与jQuery 获取父窗、子窗的iframe
2013/12/20 Javascript
js闭包的用途详解
2014/11/09 Javascript
javascript原型模式用法实例详解
2015/06/04 Javascript
一起学写js Calender日历控件
2016/04/14 Javascript
一分钟理解js闭包
2016/05/04 Javascript
AngularJS包括详解及示例代码
2016/08/17 Javascript
angular ng-repeat数组中的数组实例
2017/02/18 Javascript
JS实现复制功能
2017/03/01 Javascript
JS使用Prim算法和Kruskal算法实现最小生成树
2019/01/17 Javascript
基于JS开发微信网页录音功能的实例代码
2019/04/30 Javascript
如何利用node.js开发一个生成逐帧动画的小工具
2019/12/01 Javascript
Python实现根据指定端口探测服务器/模块部署的方法
2014/08/25 Python
python读取一个目录下所有txt里面的内容方法
2018/06/23 Python
如何优雅地改进Django中的模板碎片缓存详解
2018/07/04 Python
在Python中通过getattr获取对象引用的方法
2019/01/21 Python
Python生成MD5值的两种方法实例分析
2019/04/26 Python
TensorFlow查看输入节点和输出节点名称方式
2020/01/04 Python
python 使用while循环输出*组成的菱形实例
2020/04/12 Python
HTML5自定义元素播放焦点图动画的实现
2019/09/25 HTML / CSS
数据库面试要点基本概念
2013/10/31 面试题
读书活动总结
2014/04/28 职场文书
师德演讲稿范文
2014/05/06 职场文书
企业趣味活动方案
2014/08/21 职场文书
工程承包协议书
2014/10/20 职场文书
2014乡党委副书记党建工作汇报材料
2014/11/02 职场文书
群众路线自查报告及整改措施
2014/11/04 职场文书
2015年法制宣传月活动总结
2015/03/26 职场文书
安装harbor作为docker镜像仓库的问题
2022/06/14 Servers