将数据传递到Aurelia中尚未加载的视图
我正在从一个视图(称为bestSellersView)导航到另一个视图(BookDetailsView)。有多个不同的“父”视图可以导航到“书籍详细信息”,它们都需要将要查看的书籍传递到下一个视图。我不想像一些线程建议的那样将源代码视图注入到细节视图中,因为我的构造函数会随着使用细节子视图的每个新视图而增长 我尝试使用事件聚合器,但是由于事物的生命周期,我在第一次导航时总是会看到一个空白的详细信息屏幕。当我第一次导航到“book details”视图时,ViewDetails消息在出版商(畅销书)发送消息之前尚未订阅。由于我已将viewmodel设置为singleton,因此后续的单击工作正常(因为详细信息视图已经构建并订阅了事件) 我怎样才能避开奥雷利亚的鸡蛋问题 编辑01 以下是我遇到问题时正在做的事情: 硕士学位:将数据传递到Aurelia中尚未加载的视图,aurelia,Aurelia,我正在从一个视图(称为bestSellersView)导航到另一个视图(BookDetailsView)。有多个不同的“父”视图可以导航到“书籍详细信息”,它们都需要将要查看的书籍传递到下一个视图。我不想像一些线程建议的那样将源代码视图注入到细节视图中,因为我的构造函数会随着使用细节子视图的每个新视图而增长 我尝试使用事件聚合器,但是由于事物的生命周期,我在第一次导航时总是会看到一个空白的详细信息屏幕。当我第一次导航到“book details”视图时,ViewDetails消息在出版商(畅销书
import { JsonServiceClient } from "servicestack-client";
import {
ListPendingHoldingsFiles,
ListPendingHoldingsFilesResponse,
SendHoldings,
PositionFileInfo
} from "../holdingsManager.dtos";
import { inject, singleton } from "aurelia-framework";
import { Router } from "aurelia-router";
import { EventAggregator } from "aurelia-event-aggregator";
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage";
@singleton()
@inject(Router, EventAggregator)
export class Pending {
router: Router;
positions: PositionFileInfo[];
client: JsonServiceClient;
eventAgg: EventAggregator;
constructor(router, eventAggregator) {
this.router = router;
this.eventAgg = eventAggregator;
this.client = new JsonServiceClient('/');
var req = new ListPendingHoldingsFiles();
this.client.get(req).then((getHoldingsResponse) => {
this.positions = getHoldingsResponse.PositionFiles;
}).catch(e => {
console.log(e); // "oh, no!"
});
}
openHoldings(positionInfo) {
this.eventAgg.publish(new GetPendingPositionMessage(positionInfo));
this.router.navigate('#/holdings');
}
}
Child.ts:
import { JsonServiceClient } from "servicestack-client";
import { inject, singleton } from "aurelia-framework";
import { Router } from 'aurelia-router';
import { EventAggregator } from "aurelia-event-aggregator";
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage";
import {
GetPendingHoldingsFile,
GetPendingHoldingsFileResponse,
Position,
PositionFileInfo
} from "../holdingsManager.dtos";
@singleton()
@inject(Router, EventAggregator)
export class Holdings {
router: Router;
pendingPositionFileInfo: PositionFileInfo;
position: Position;
client: JsonServiceClient;
eventAgg: EventAggregator;
constructor(router, eventAggregator) {
this.router = router;
this.eventAgg = eventAggregator;
this.eventAgg.subscribe(GetPendingPositionMessage,
message => {
this.pendingPositionFileInfo = message.fileInfo;
});
}
activate(params, routeData) {
this.client = new JsonServiceClient('/');
var req = new GetPendingHoldingsFile();
req.PositionToRetrieve = this.pendingPositionFileInfo;
this.client.get(req).then((getHoldingsResponse) => {
this.position = getHoldingsResponse.PendingPosition;
}).catch(e => {
console.log(e); // "oh, no!"
});
}
}
以下是我现在正在做的事情:
硕士
import { JsonServiceClient } from "servicestack-client";
import {
ListPendingHoldingsFiles,
ListPendingHoldingsFilesResponse,
PositionFileInfo
} from "../holdingsManager.dtos";
import { inject, singleton } from "aurelia-framework";
import { Router } from "aurelia-router";
import { EventAggregator } from "aurelia-event-aggregator";
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage";
import { SetPendingPositionMessage } from "../common/SetPendingPositionMessage";
@singleton()
@inject(Router, EventAggregator)
export class Pending {
router: Router;
eventAgg: EventAggregator;
positions: PositionFileInfo[];
client: JsonServiceClient;
fileInfo: PositionFileInfo;
constructor(router, eventAggregator) {
this.router = router;
this.eventAgg = eventAggregator;
this.eventAgg.subscribe(GetPendingPositionMessage, () => {
this.eventAgg.publish(new SetPendingPositionMessage(this.fileInfo));
});
}
activate(params, routeData) {
this.client = new JsonServiceClient('/');
var req = new ListPendingHoldingsFiles();
this.client.post(req).then((getHoldingsResponse) => {
this.positions = getHoldingsResponse.PositionFiles;
}).catch(e => {
console.log(e); // "oh, no!"
});
}
openHoldings(positionInfo) {
this.fileInfo = positionInfo;
this.router.navigate('#/holdings');
}
}
child.ts
import { JsonServiceClient } from "servicestack-client";
import { inject, singleton } from "aurelia-framework";
import { Router } from 'aurelia-router';
import {
GetPendingHoldingsFile,
GetPendingHoldingsFileResponse,
Position,
SendHoldings,
PositionFileInfo
} from "../holdingsManager.dtos";
import { EventAggregator } from "aurelia-event-aggregator";
import { GetPendingPositionMessage } from "../common/GetPendingPositionMessage";
import { SetPendingPositionMessage } from "../common/SetPendingPositionMessage";
import { GetDeliveredPositionMessage } from "../common/GetDeliveredPositionMessage";
import { SetDeliveredPositionMessage } from "../common/SetDeliveredPositionMessage";
@singleton()
@inject(Router, EventAggregator)
export class Holdings {
router: Router;
pendingPositionFileInfo: PositionFileInfo;
position: Position;
client: JsonServiceClient;
eventAgg: EventAggregator;
constructor(router, eventAggregator) {
this.router = router;
this.eventAgg = eventAggregator;
this.eventAgg.subscribe(SetPendingPositionMessage, message => this.getPositionData(message.fileInfo));
this.eventAgg.subscribe(SetDeliveredPositionMessage, message => this.getPositionData(message.fileInfo));
}
getPositionData(fileInfo) {
this.position = null;
this.client = new JsonServiceClient('/');
var req = new GetPendingHoldingsFile();
req.PositionToRetrieve = fileInfo;
this.client.post(req).then((getHoldingsResponse) => {
this.position = getHoldingsResponse.PendingPosition;
}).catch(e => {
console.log(e); // "oh, no!"
});
}
activate(params) {
this.eventAgg.publish(new GetPendingPositionMessage());
this.eventAgg.publish(new GetDeliveredPositionMessage());
}
sendHoldings() {
var req = new SendHoldings();
this.client.get(req).then((sendHoldingsRepsonse) => {
console.log("SUCCESS!"); // "oh, no!"
}).catch(e => {
console.log(e); // "oh, no!"
});
}
}
我需要为孩子的activate方法添加一点逻辑,以确保我请求的是正确的家长持股文件。我当前的解决方案,尽管没有我希望的那么漂亮,但如下所示: 源代码视图(bestSellersView)是一个单例视图,订阅“GetCurrentBookMessage”。当用户选择一本书时,源将其保存在本地并导航到“BookDetailsView”。BookDetailsView被构造,订阅一个“SetCurrentBookMessage”,当激活时,它发送一个GetCurrentBookMessage。源代码视图以“SetCurrentBookMessage”回答 这将与多个来源变得混乱,我将不得不有一些方法来解决导航从何而来,以选择“正确”的来源,但对于今天的工作 编辑01 我还尝试过去掉所有事件聚合器的东西,并将其放入master的OpenHoldings方法中:
let routeConfig = this.router.routes.find(x => x.name === 'holdings');
this.fileInfo = positionInfo;
routeConfig.settings = {
fileInfo: positionInfo
};
this.router.navigateToRoute('holdings');
然后将其放入孩子的激活方法中:
activate(urlParams, routeMap, navInstr) {
this.getPositionData(routeMap.settings.fileInfo);
}
但是,在执行导航后,这些设置没有保持不变。听起来您需要在视图之间共享状态。我使用一个
StateStore
类,该类被注入任何希望共享状态的视图中。默认情况下,所有注入的对象都是单例对象,因此很容易共享状态。一个非常简单的例子可以是(在TypeScript中):
statestore.ts
export class StateStore {
state: any;
}
masterview.ts
autoinject()
export class MasterView {
constructor(private store: StateStore){
}
doSomething(): void {
this.store.state = "some value";
// navigate to detail view
}
}
detailview.ts
autoinject()
export class DetailView {
sharedValue: any;
constructor(store: StateStore) {
this.sharedValue = store.state;
}
}
这将在视图之间共享
StateStore
的单个实例,以便轻松共享状态。我们需要查看一些代码,看看您是如何操作的,看看我们可以提供什么帮助。@KellyEthridge我添加了一些代码进行比较。看起来您只是试图在视图之间共享状态。当从主视图->详细视图导航时需要共享时,我注入状态存储。我不确定关于构造函数注入,您指的是什么线程。我可能不完全理解您的场景或您引用的线程。基本上,我看到有人建议人们使用构造函数注入在其子viewmodel中引用父viewmodel。然后子对象直接从父对象访问所需的值。如果我理解正确的话,您是否向名为“状态存储”的IOC容器注册了一个单独的对象,并将其注入父级和子级?这正是我所做的。默认情况下,所有注入的对象都是单例对象,所以除了正常注入外,我不必做任何其他事情。然后使用set/get方法来处理我需要的任何状态。@KellyEthridge我想我喜欢状态存储方法。它大大简化了我的逻辑,而且我不必乱弄订阅。谢谢@KellyEthridge刚刚实现了StateStore,非常漂亮。简单,容易,而且工作起来很漂亮。如果您正在收集统计数据,只需发布一行回答:StateStore查看其他评论。。。我很乐意给你一点荣誉。