问题: angular 从子状态回到当前的父级状态的时候,父级状态不会重新初始化。

https://github.com/angular-ui/ui-router/issues/2992

原文:https://medium.com/engineering-on-the-incline/reloading-current-route-on-click-angular-5-1a1bfc740ab2

------------------------------------------------

Back in the days of AngularJS you were able to reload a route even if you were already viewing it. For example, clicking on the home option of a menu when you are already viewing the homepage would refresh the homepage. This was useful for a number of reasons, but most importantly for UX. Users expect to be able to click on a page menu item and have the page re-initialise. Setting up this type of reloading in AngularJS was straightforward. You could invoke reload() in your router and away you went.

When Angular 2 was released this feature was not present in the router and there was no easy way to reload the active route. Many people developed “hacky” techniques such as bouncing through a second route in the A -> B -> A sequence, effectively sending you off to a page and back again to trigger the reload. That had the desired effect but was rather inefficient. Another technique that was often suggested was outright reloading the page, which for a single page application is a bad idea.

As of Angular 5.1 there is a supported technique for route reloading. This can now be done using the onSameUrlNavigation
configuration option as part of the built-in Angular router. Unfortunately, the documentation does not make it very clear on how to implement it, so I have documented my approach below.

The first thing you will need to do is set the option within your app.routing.tsif you have one, or the file where your app routing is configured in your particular project.

There are two possible values for onSameUrlNavigation ’reload’ or false. The default value is false, causing nothing to happen when the router is asked to navigate to the active route. We want to set this value to reload. It is worth noting reload does not actually do the work of reloading the route, it only re-triggers events on the router that we then need to hook into.

@ngModule({
imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: ‘reload’})],
exports: [RouterModule],
})

To determine how those events are actually fired, you need to specify the runGuardsAndResolvers configuration option on your route. This can take one of three values

paramsChange — only fire when route params have changed e.g. where the id in /user/:id changes

paramsOrQueryParamsChange — fire when a route param changes or a query param changes. e.g. the id or the limit property change in /user/:id/invites?limit=10

always — Always fire when the route is navigated

We want to specify always in this case. An example route definition is shown below.

export const routes: Routes = [
{
path: ‘invites’,
component: InviteComponent,
children: [
{
path: ‘’,
loadChildren: ‘./pages/invites/invites.module#InvitesModule’,
},
],
canActivate: [AuthenticationGuard],
runGuardsAndResolvers: ‘always’,
}
]

With these two changes your router is configured. The next step is to handle the events that your router will produce within one of your components. To do this you will need to import the Router into your component and then hook into the events of interest. In this example, I have hooked into the NavigationEnd event which is fired once the router has completed its navigation from one route to another. Due to the way we have configured the app, this will now fire even if you try to navigate to the current route.

export class InviteComponent implements OnInit, OnDestroy{
 // ... your class variables here
navigationSubscription;
 constructor(
// … your declarations here
private router: Router,
) {
// subscribe to the router events - storing the subscription so
// we can unsubscribe later.
   this.navigationSubscription = this.router.events.subscribe((e: any) => {
// If it is a NavigationEnd event re-initalise the component
if (e instanceof NavigationEnd) {
this.initialiseInvites();
}
});
} initialiseInvites() {
// Set default values and re-fetch any data you need.
}
 ngOnDestroy() {
// avoid memory leaks here by cleaning up after ourselves. If we
// don't then we will continue to run our initialiseInvites()
// method on every navigationEnd event.
if (this.navigationSubscription) {
this.navigationSubscription.unsubscribe();
}
}
}

The heavy lifting goes into the initialiseInvites() method, this is where you reset properties to their default values and fetch data from services to get the component back to its initial state.

You need to repeat this pattern across each component that you would like to to reload, being sure to add the runGuardsAndResolvers option to each route in the routing file.

** Updated 05/03/2018 **

Thanks to Changyu Geng and Dennis de Laat for pointing this out in the comments.

I have added an unsubscribe handler in the ngOnDestroy hook in the above example.

As router.events is global, if we do not unsubscribe our event handler on component destruction then it will continue to fire for every NavigationEndevent across our application even when we are not on the invites screen. This is less than ideal because

a) We will be running our event handler for invites even if we are on another screen.

b) Every time we navigate back to invites we will resubscribe to the event. This would cause our initialise function to run n times, where n is the number of times we have landed on the invites page.


If you’ve enjoyed this blog, please take a couple of minutes to check out Gurn and see how it can make you a more productive developer.

---------------------------------------------------------------------------

2
 

I want to extract only the last event entry of type NavigationEnd from router.events. But somehow I can't find a proper way to do this. Whatever I try the following code snipped is the only way to get access to these objects of interest.

let ne: any;

router.events.filter(e => e instanceof NavigationEnd)
.forEach(e => {
ne = e as NavigationEnd;
}); console.log('target page: ', ne.urlAfterRedirects);

But do I really have to use .forEach() letting it run though all entries and using then the last entry? Isn't there a better way to handle the events as a kind of array and then say

ne = arrayOfEvents[arrayOfEvents.length-1]

?

I'm getting crazy about it but it seems that I can't see the wood for the trees...

asked Apr 8 '18 at 20:19
Lynx 242

4,91741836

2 Answers

4
 

Okay, after reading through the posted articles above and rethinking what I really want to achieve I found out that my approach was definitely too complicated. Because actually I only need access to the currently called route. And so I started from scratch and came across this small but very effective solution:

this.router.events.subscribe(value => {
console.log('current route: ', router.url.toString());
});

Thanks to all who shared a comment in oder to support me! It helped al lot as I was able to tie up loose ends.

answered Apr 8 '18 at 21:16
Lynx 242

4,91741836
4

PS. There's a better way to filter using a 'typeguard', you then get the proper type without having to assert it again:

firstChildData$ = this.router.events.pipe(

            filter((e): e is NavigationEnd => e instanceof NavigationEnd), 

            map(e => { // e is now NavigationEnd }

This is actually necessary in strict mode.

Reloading current route in Angular 5 / Angular 6 / Angular 7的更多相关文章

  1. Angular学习笔记:Angular CLI

    定义 Angular CLI:The Angular CLI is a command line interface tool that can create a project, add files ...

  2. angular enter事件,angular回车事件

    angular回车键搜索,angular enter搜索 对于搜索框,用户在输入内容后的搜索习惯不是鼠标点击搜索按钮,而是直接按enter键,那我们怎么给enter键绑定事件呢,其实很简单,代码如下: ...

  3. Angular 2 升级到 Angular 5

    Angular 2 升级到 Angular 5 ts文件最上面的import语句里不要添加 .ts 后缀 , 不然 npm start 编译会失败 . 虽然浏览器能打开项目的URL , 但是内容会丢失 ...

  4. Angular系列一:Angular程序架构

    Angular程序架构 Angular程序架构 组件:一段带有业务逻辑和数据的Html服务:用来封装可重用的业务逻辑指令:允许你向Html元素添加自定义行为模块: 环境搭建 安装nodeJs安装好no ...

  5. Angular系列文章之angular路由

    路由(route),几乎所有的MVC(VM)框架都应该具有的特性,因为它是前端构建单页面应用(SPA)必不可少的组成部分. 那么,对于angular而言,它自然也有内置的路由模块:叫做ngRoute. ...

  6. [Angular 2] ROUTING IN ANGULAR 2 REVISITED

    Let's say we have a list of contacts, click each contact, we can render a new route to get the detai ...

  7. Angular - 预加载 Angular 模块

    Angular - 预加载延迟模块 在使用路由延迟加载中,我们介绍了如何使用模块来拆分应用,在访问到这个模块的时候, Angular 加载这个模块.但这需要一点时间.在用户第一次点击的时候,会有一点延 ...

  8. Angular企业级开发(3)-Angular MVC实现

    1.MVC介绍 Model-View-Controller 在20世纪80年代为程序语言Smalltalk发明的一种软件架构.MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并 ...

  9. 30行代码让你理解angular依赖注入:angular 依赖注入原理

    依赖注入(Dependency Injection,简称DI)是像C#,java等典型的面向对象语言框架设计原则控制反转的一种典型的一种实现方式,angular把它引入到js中,介绍angular依赖 ...

随机推荐

  1. SCART概念

    SCART(Syndicat des Constructeursd' Appareils Radiorécepteurs et Téléviseurs)接口是一种专用的音视频接口,它是由法国公司Per ...

  2. POJ2449 【第k短路/A*】

    题目链接:http://poj.org/problem?id=2449 题目大意: 给出n个点,m条有向边,最后一行给出起点到终点的第k短路.求长度. 题解思路: 这是我第一道第k短路题以及A*算法的 ...

  3. 点亮文字(CSS)

    html <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8& ...

  4. 简单谈一谈Java内部类的使用原因

    使用内部类的原因 学习总得知其所以然,前面的一篇文章中我有提到过关于java内部类的几种用法以及一些示例,但是不明白内部类具体可以做什么,显然学习起来很渺茫,今天的文章简单说一说使用内部类的几个原因, ...

  5. [转帖]详解Linux系统inode原理--硬链接、软链接、innodb大小和划分等

    详解Linux系统inode原理--硬链接.软链接.innodb大小和划分等 原创 波波说运维 2019-07-17 00:03:00 https://www.toutiao.com/i6713116 ...

  6. Spring boot+Websocket实例1

    简单的demo https://github.com/callicoder/spring-boot-websocket-chat-demo

  7. 数据结构 -- 哈希表(hash table)

    简介   哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函 ...

  8. Netty源码剖析-关闭服务

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:  ----源码: 先在服务端加个断点和修改下代码:如 ...

  9. (七)Session 对象知识点总结(来自那些年的笔记)

    如果你想要转载话,可不可以不要删掉下面的 作者信息 呀!: 作者:淮左白衣 写于 来源笔者自己之前学javaWeb的时候,写的笔记 : 目录 Session对象 Session和cookie的主要区别 ...

  10. Linux/ubuntu 心得

    基本命令 有n个软件未被升级(有强迫症的,不爽的 apt-get dist-upgrade 更改主机名字 git 不要免密输入的话,可在当前工作目录执行 git config credential.h ...