簡體   English   中英

將全局對象/模型傳遞給Aurelia中的自定義元素

[英]Pass global Object/Model to custom element in Aurelia

參考下面的StackOverflow問題。我有一個非常不同的場景,我想知道Aurelia是否有解決方案。

場景:

我有一個用戶模型:

export class User{
    @bindable name: string;
    @bindable address: Address

如您所見,“地址”是一個子模型。

我有一個主要的視圖模型“注冊”。 在此視圖模型中,我有一個模型“用戶”:

export class RegistrationView{
    @bindable user: User

    public attached(){
        this.user = userService.fetchUserFromApi();
    }

除此之外,我還有一個自定義元素“用戶地址”,其中有一個“用戶地址”模型(因為我想擁有專用的封裝自定義元素)。

export class userAddress{
    @bindable userAddress: Address

現在,我只想從API請求用戶模型一次,然后將用戶地址發送給自定義元素:

<template>
  <require from="user-address"></require>

  <user-address user.address.bind="${dj.address}"></user-address>

最后,我將(擁有專用的封裝自定義元素,可以在任何地方使用)檢查附加方法是否已經加載了用戶,如果尚未加載,則自定義元素將加載所有需要的數據:

export class userAddress{
    @bindable userId: string
    @bindable address: Address

    public attached(){
        if(!(typeof this.address === "undefined")){
             this.address = this.addressAPIService.getAddressByUserId(id)
        }
    }
  1. 問題1 :我知道,提到的模板dj.address.bind不起作用。 但是現在我的問題是,我該如何處理這種情況?
  2. 問題2 :如何確保該用戶對象只被請求一次?
  3. 我的概念是否有意義,是否是Aurelia的想法?

如果我正確理解了您的問題,則只需要某種形式的客戶端持久性。

如果即使在用戶關閉瀏覽器后仍需要這種持久性,則需要使用localStorage或其某些封裝。 有很多不錯的插件可用,例如localForageLokiJS和最近開發的(仍處於beta中)aurelia插件aurelia-store

您可能希望將用戶的檢索封裝在某種UserService中。 這不是Aurelia特有的,只是一般而言,您希望在大多數類型的應用程序中執行此操作。

因此,在您的視圖模型中,您可能會有類似的內容(跳過一些實現細節,例如檢查參數,配置路由器等以簡化篇幅):

@autoinject()
export class UserViewModel {
  public user: User;

  constructor(private userService: UserService){}

  // happens before bind or attached, so your child views will always have the user in time
  public async activate(params: any): Promise<void> {
    this.user = await this.userService.getUserById(params.id);
  }
}

並在您的用戶服務中:

// singleton will ensure this service lives as long as the app lives
@singleton() 
export class UserService {
  // create a simple cache object to store users
  private cache: any = Object.create(null); 

  constructor(private client: HttpClient) {}

  public async getUserById(id: number): Promise<User> {
    let user = this.cache[id];
    if (user === undefined) {
      // immediately store the user in cache
      user = this.cache[id] = await this.client.fetch(...);
    }
    return user;
  }
}

讓您的視圖模型變得愚蠢,並在需要加載用戶時調用UserService,讓您的服務變得聰明,僅在尚未緩存時才從API中獲取它。

我還想指出,當您要獲取數據時, attached()不是。 attached()是執行DOM內容(添加/刪除元素,樣式,其他修飾性內容)時的內容。 最好bind()限制為抓取/處理客戶端上已有的數據。

那么何時獲取數據?

在路由生命周期中的路由視圖模型中。 那將是configureRoutercanActivateactivatecanDeactivatedeactivate 這些將在涉及任何DOM之前遞歸解決。

不在您的自定義元素中。 否則,您很快就會因為通知機制和額外的綁定而陷入維護困境,以便組件可以彼此告知“現在可以安全渲染,因為我有數據”。

如果您的自定義元素可以假設tehy有自己的數據一旦bind()發生,一切都變得簡單了很多管理。

用戶調用的API調用又如何呢?

比您想像的要多,您可以讓操作成為路線而不是直接方法。 您可以無限嵌套router-view ,它們實際上不必是頁面,它們可以像您想要的一樣細粒度。

當可以通過特定路線直接訪問小的子視圖時,它增加了很多可訪問性。 它為您提供了額外的功能來處理授權,未保存的更改和排序的警告,用戶的后退/前進導航等。

對於所有其他情況:

像通常在activate()期間一樣,從事件觸發的方法調用服務,除非通常路由器將頁面加載推遲到數據在那里,現在您必須為該元素自己做。

最簡單的方法是使用if.bind="someEntityThatCanBeUndefined" 該元素僅在該對象具有值時才呈現。 而且它不需要處理獲取數據的基礎結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM