浅谈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 相关文章推荐
JsEasy简介 JsEasy是什么?与下载
Mar 07 Javascript
JQuery事件e参数的方法preventDefault()取消默认行为
Sep 26 Javascript
jQuery中:radio选择器用法实例
Jan 03 Javascript
jQuery原生的动画效果
Jul 10 Javascript
Javascript oop设计模式 面向对象编程简单实例介绍
Dec 13 Javascript
详解如何从零开始搭建Express+Vue开发环境
Jul 17 Javascript
vue中关闭eslint的方法分析
Aug 04 Javascript
vue 2.8.2版本配置刚进入时候的默认页面方法
Sep 21 Javascript
解决使用layui对select append元素无效或者未及时更新的问题
Sep 18 Javascript
JavaScript实现滑动门效果
Jan 18 Javascript
vue实现登录拦截
Jun 29 Javascript
微信小程序自定义底部弹出框动画
Nov 18 Javascript
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
php 安全过滤函数代码
2011/05/07 PHP
PHP 面向对象程序设计(oop)学习笔记(三) - 单例模式和工厂模式
2014/06/12 PHP
PHP实现合并discuz用户
2015/08/05 PHP
PHP二维数组去重实例分析
2016/11/18 PHP
PHP基于pdo的数据库操作类【可支持mysql、sqlserver及oracle】
2018/05/21 PHP
json的前台操作和后台操作实现代码
2012/01/20 Javascript
js实现杯子倒水问题自动求解程序
2013/03/25 Javascript
利用jQuery中的ajax分页实现代码
2016/02/25 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
2016/03/04 Javascript
JS实时弹出新消息提示框并有提示音响起的实现代码
2016/04/20 Javascript
jQuery实现可以编辑的表格实例详解【附demo源码下载】
2016/07/09 Javascript
利用Angularjs和原生JS分别实现动态效果的输入框
2016/09/01 Javascript
JavaScript学习笔记整理_简单实现枚举类型,扑克牌应用
2016/09/19 Javascript
浅谈对Angular中的生命周期钩子的理解
2017/07/31 Javascript
基于webpack 实用配置方法总结
2017/09/28 Javascript
vue.js实现简单轮播图效果
2017/10/10 Javascript
Vue+ElementUI实现表单动态渲染、可视化配置的方法
2018/03/07 Javascript
Vue微信项目按需授权登录策略实践思路详解
2018/05/07 Javascript
JavaScript设计模式之建造者模式实例教程
2018/07/02 Javascript
vue axios 简单封装以及思考
2018/10/09 Javascript
点击按钮弹出模态框的一系列操作代码实例
2019/03/29 Javascript
js获取浏览器地址(获取第1个斜杠后的内容)
2019/09/03 Javascript
js如何验证密码强度
2020/03/18 Javascript
Angular处理未可知异常错误的方法详解
2021/01/17 Javascript
[03:48]2014DOTA2 TI专访71DK夺冠不靠小组赛高排名
2014/07/11 DOTA
《Python之禅》中对于Python编程过程中的一些建议
2015/04/03 Python
python创建关联数组(字典)的方法
2015/05/04 Python
浅谈Keras中shuffle和validation_split的顺序
2020/06/19 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
世界闻名的衬衫制造商:Savile Row Company
2018/07/30 全球购物
党的生日演讲稿
2014/09/10 职场文书
农村党建工作汇报材料
2014/10/27 职场文书
先进基层党组织材料
2014/12/25 职场文书
保管员岗位职责
2015/02/14 职场文书
法定授权委托证明书
2015/06/18 职场文书
Matplotlib绘制混淆矩阵的实现
2021/05/27 Python