问题: 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. U盘防病毒

    1.待查 http://jingyan.baidu.com/article/a3f121e4ced14ffc9052bbca.html

  2. Java面试 - PATH与CLASSPATH 的区别?

    PATH:操作系统提供的路径配置,用于定义所有可执行程序的路径. CLASSPATH:由JRE提供的,用于定义Java 程序解释时类加载路径.

  3. 7个步骤让PC网站自动适配手机网页

    传统的网站如何完成向移动设备的快速转型? 通过移动适配技术可以实现,切图网是国内首家基于web技术服务的公司,而移动适配主要通过底层的web技术开发手段来完成,下面切图网将从技术角度来告诉你通过7个步 ...

  4. oracle导入.dmp脚本

    一.更改数据库管理员sys/system密码 1.运行到C盘根目录 2.输入:SET ORACLE_SID = 你的SID名称 3.输入:sqlplus /nolog 4.输入:connect /as ...

  5. 【坑】Mybatis 多次逆向工程生成mapper文件

    在使用 mybatis 逆向工程的时候,多次逆向工程生成的文件,是不会产生覆盖的,而是追加: 假如,你第一次逆向,发生数据库的某个字段类型错了,修改以后再次逆向,那么得到的 mapper文件,将是 2 ...

  6. VC++单文档程序固定菜单栏和工具栏

    MainFrm.cpp框架类下,找到OnCreate方法 m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY); m_wndToolBar.EnableDocking( ...

  7. Python复习笔记02

    语句表达式: 在Python中支持遍历循环的对象:可迭代器对象,支持迭代协议的对象 比如列表list没有迭代功能只是可迭代对象 迭代:迭代协议 --> 例:f.__next__() 属于f的迭代 ...

  8. SAS学习笔记21 散点图、条形图

  9. python几个轻量级web框架

    python几个轻量级web框架 2016-04-11 18:04:34 惹不起的程咬金 阅读数 7944更多 分类专栏: 云计算/大数据/并行计算 Python   我最近发表了一篇名为 ‘7 Mi ...

  10. SQL查询oracle数据库最近备份情况

    需求,查询RMAN备份情况,通过视图进行查询 SQL> //,) input_g, round(OUTPUT_BYTES///,) output_g order by ; SID OUTPUT_ ...