Aurelia Routing - 防止视图交换以每次实例化新的视图模型
Aurelia Routing - Prevent view swapping to instantiate new view model each time
我的问题是:当我们在路由器视图之间交换时,是否可以保持路由器视图的相同视图模型实例?
我解释一下我的问题:感谢 EventAggregator
,我想让路由器子组件进行通信。我的一个路由器子组件在单击按钮时发布一条消息,另一个订阅它。
这是订阅该事件的组件中的代码:
constructor(private ea: EventAggregator) {
ea.subscribe(GameInfo, msg => console.log(msg));
}
当我单击我的按钮时,我会在控制台中看到多个日志(或 none),具体取决于我导航到正在订阅的视图的次数。
这是我的路由器组件:
import {Router, RouterConfiguration} from 'aurelia-router';
export class Playground {
public router: Router;
public configureRouter(config: RouterConfiguration, router: Router) {
config.map([
{ route: ['', 'media-creator'], name: 'media-creator', moduleId: './media-creator/media-creator', nav: true, title: 'Media Creator' },
{ route: 'board-initializer', name: 'board-initializer', moduleId: './board-initializer/board-initializer', nav: true, title: 'Board Initializer' },
{ route: 'code-editor', name: 'code-editor', moduleId: './code-editor/code-editor', nav: true, title: 'Code Editor' }
]);
this.router = router;
}
}
我想将信息从 Board Initializer 发送到代码编辑器,并且我需要在通过路由器导航时保持每个组件的状态。
也许无法阻止此机制,我的解决方案是使用 bootstrap nav-tabs/data-toggle.
感谢您对此的任何见解。
我最近看到了很多关于在导航时保持状态的问题。视图模型在不再需要时被解构,因此您无法使用您显示的路由器配置从视图模型本身维护状态。
您有两个选择:
1) 将服务注入到需要在该服务内的队列中进行通信和跟踪消息的两个视图模型中。当您四处浏览时,检查队列并按顺序处理消息。这不是完美的解决方案,但只要队列不会变得太大,它就会起作用。
2) 创建一个路由并向路由添加一个参数来表示哪个页面应该可见,然后将两个视图模型作为组件放在页面上,并将 show.bind 放在路由参数上。当你想切换组件时仍然调用 router.navigateToRoute() 但指向相同的路由(只需更改组件可见的参数)。您还需要将激活策略设置为 "invokeLifecycle" 以便调用视图模型的路由器生命周期挂钩并处理路由参数的值。这里的好处是两个组件的视图模型将保持活动状态,因此它们可以继续相互传递消息,并且对于用户来说,它们仍然看起来好像在页面之间导航。如果您不关心更新 URL 那么当然您可以跳过所有这些并只在本地跟踪变量。
我可以在电脑旁写出代码示例
附带说明一下,不要在构造函数中订阅事件聚合器,因为您已经注意到您会获得多个订阅。在激活或附加中订阅,然后在停用或分离中取消订阅。
首先,关于多次添加事件侦听器的问题 - 您需要更改添加它的方式,然后还要确保在分离当前 VM 时将其删除。
下面,我从优秀的 ILikeKillNerds.com 博客中获取了代码 - 老实说,它有时是救命稻草。
https://ilikekillnerds.com/2016/02/working-with-the-aurelia-event-aggregator/
import { inject } from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';
@inject(EventAggregator)
export class MyClass {
constructor(EventAggregator) {
this.ea = EventAggregator;
}
attached() {
this.subscriber = this.ea.subscribe('puppyMonkeyBaby', response => {
console.log(response.testValue);
});
}
detached() {
this.subscriber.dispose();
}
}
如您所见,事件侦听器是在 attached()
方法中添加的,然后在(不出所料)detached()
.
中分离 VM 时重要地被删除
存储状态更难,正如 Mgiesa 所介绍的那样,有几种不同的方法来处理它,这实际上取决于您的用例。
就我个人而言,我会考虑使用 class 作为单例,它被注入到每个不同的视图模型中并允许您共享状态。
再一次,优秀的 ILikeKillNerds.com 提供了关于此的精彩博客;
https://ilikekillnerds.com/2016/02/shared-state-in-aurelia/
注入视图模型(不使用 NewInstance.of()
)的任何 class 都将被视为单例。
我的问题是:当我们在路由器视图之间交换时,是否可以保持路由器视图的相同视图模型实例?
我解释一下我的问题:感谢 EventAggregator
,我想让路由器子组件进行通信。我的一个路由器子组件在单击按钮时发布一条消息,另一个订阅它。
这是订阅该事件的组件中的代码:
constructor(private ea: EventAggregator) {
ea.subscribe(GameInfo, msg => console.log(msg));
}
当我单击我的按钮时,我会在控制台中看到多个日志(或 none),具体取决于我导航到正在订阅的视图的次数。
这是我的路由器组件:
import {Router, RouterConfiguration} from 'aurelia-router';
export class Playground {
public router: Router;
public configureRouter(config: RouterConfiguration, router: Router) {
config.map([
{ route: ['', 'media-creator'], name: 'media-creator', moduleId: './media-creator/media-creator', nav: true, title: 'Media Creator' },
{ route: 'board-initializer', name: 'board-initializer', moduleId: './board-initializer/board-initializer', nav: true, title: 'Board Initializer' },
{ route: 'code-editor', name: 'code-editor', moduleId: './code-editor/code-editor', nav: true, title: 'Code Editor' }
]);
this.router = router;
}
}
我想将信息从 Board Initializer 发送到代码编辑器,并且我需要在通过路由器导航时保持每个组件的状态。
也许无法阻止此机制,我的解决方案是使用 bootstrap nav-tabs/data-toggle.
感谢您对此的任何见解。
我最近看到了很多关于在导航时保持状态的问题。视图模型在不再需要时被解构,因此您无法使用您显示的路由器配置从视图模型本身维护状态。
您有两个选择:
1) 将服务注入到需要在该服务内的队列中进行通信和跟踪消息的两个视图模型中。当您四处浏览时,检查队列并按顺序处理消息。这不是完美的解决方案,但只要队列不会变得太大,它就会起作用。
2) 创建一个路由并向路由添加一个参数来表示哪个页面应该可见,然后将两个视图模型作为组件放在页面上,并将 show.bind 放在路由参数上。当你想切换组件时仍然调用 router.navigateToRoute() 但指向相同的路由(只需更改组件可见的参数)。您还需要将激活策略设置为 "invokeLifecycle" 以便调用视图模型的路由器生命周期挂钩并处理路由参数的值。这里的好处是两个组件的视图模型将保持活动状态,因此它们可以继续相互传递消息,并且对于用户来说,它们仍然看起来好像在页面之间导航。如果您不关心更新 URL 那么当然您可以跳过所有这些并只在本地跟踪变量。
我可以在电脑旁写出代码示例
附带说明一下,不要在构造函数中订阅事件聚合器,因为您已经注意到您会获得多个订阅。在激活或附加中订阅,然后在停用或分离中取消订阅。
首先,关于多次添加事件侦听器的问题 - 您需要更改添加它的方式,然后还要确保在分离当前 VM 时将其删除。
下面,我从优秀的 ILikeKillNerds.com 博客中获取了代码 - 老实说,它有时是救命稻草。
https://ilikekillnerds.com/2016/02/working-with-the-aurelia-event-aggregator/
import { inject } from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';
@inject(EventAggregator)
export class MyClass {
constructor(EventAggregator) {
this.ea = EventAggregator;
}
attached() {
this.subscriber = this.ea.subscribe('puppyMonkeyBaby', response => {
console.log(response.testValue);
});
}
detached() {
this.subscriber.dispose();
}
}
如您所见,事件侦听器是在 attached()
方法中添加的,然后在(不出所料)detached()
.
存储状态更难,正如 Mgiesa 所介绍的那样,有几种不同的方法来处理它,这实际上取决于您的用例。
就我个人而言,我会考虑使用 class 作为单例,它被注入到每个不同的视图模型中并允许您共享状态。
再一次,优秀的 ILikeKillNerds.com 提供了关于此的精彩博客;
https://ilikekillnerds.com/2016/02/shared-state-in-aurelia/
注入视图模型(不使用 NewInstance.of()
)的任何 class 都将被视为单例。