将数据传递到Aurelia中尚未加载的视图

将数据传递到Aurelia中尚未加载的视图,aurelia,Aurelia,我正在从一个视图(称为bestSellersView)导航到另一个视图(BookDetailsView)。有多个不同的“父”视图可以导航到“书籍详细信息”,它们都需要将要查看的书籍传递到下一个视图。我不想像一些线程建议的那样将源代码视图注入到细节视图中,因为我的构造函数会随着使用细节子视图的每个新视图而增长 我尝试使用事件聚合器,但是由于事物的生命周期,我在第一次导航时总是会看到一个空白的详细信息屏幕。当我第一次导航到“book details”视图时,ViewDetails消息在出版商(畅销书

我正在从一个视图(称为bestSellersView)导航到另一个视图(BookDetailsView)。有多个不同的“父”视图可以导航到“书籍详细信息”,它们都需要将要查看的书籍传递到下一个视图。我不想像一些线程建议的那样将源代码视图注入到细节视图中,因为我的构造函数会随着使用细节子视图的每个新视图而增长

我尝试使用事件聚合器,但是由于事物的生命周期,我在第一次导航时总是会看到一个空白的详细信息屏幕。当我第一次导航到“book details”视图时,ViewDetails消息在出版商(畅销书)发送消息之前尚未订阅。由于我已将viewmodel设置为singleton,因此后续的单击工作正常(因为详细信息视图已经构建并订阅了事件)

我怎样才能避开奥雷利亚的鸡蛋问题

编辑01

以下是我遇到问题时正在做的事情:

硕士学位:

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查看其他评论。。。我很乐意给你一点荣誉。