两个可观察变量相互依赖

时间:2016-01-18 21:03:42

标签: angularjs angular

我需要有关如何使可观察变量currentShop依赖于变量shopList的建议。

AppComponent通过shopList读取shopProvider。它没有问题,但我需要修改代码以从加载的商店设置currentShop

感谢。

AppComponent:

export class AppComponent {

    currentShop;
    shopList;

    constructor(router: Router,shopProvider:ShopProvider){
        this.shopList = shopProvider.shops;
        this.currentShop = shopProvider.currentShop;

        shopProvider.loadShops();
        shopProvider.setCurrentShop(-1);

        router.navigate(['/System']);
    }
}

ShopProvider:

export class ShopProvider{

    private _http:Http;

    shops:Observable<Array<Shop>>;

    currentShop:Observable<Shop>;

    private obServer:any;

    private _shopDataStore : {
        shops: Array<Shop>
    }

    constructor(http:Http){
        this._http = http;
        this.shops = new Observable(observer => this.obServer = observer).share();
        //this.currentShop = ??
        this._shopDataStore = {shops: []};
    }

    setCurrentShop(shopId:number){
       //Code ??
    }

    loadShops(){
        this._http
            .get('/services/shop/list')
            .map(res => res.json())
            .subscribe(data => {
                this._shopDataStore.shops = data;
                this.obServer.next(this._shopDataStore.shops);
            })
    }
}

HTML:

<div>{{currentShop.name | async}}</div>

<ul>
    <li *ngFor="#shop of shopList | async">
        <a [routerLink]="['/Shop', {shopId: shop.id}]">
            <span>{{shop.name}}</span>
        </a>
    </li>
</ul>

2 个答案:

答案 0 :(得分:3)

我会选择更类似的架构:

<强> ShopService

class Shop {
  constructor(public shopId: Number, public shopName: string) {}
}

@Injectable()
class ShopService {
  shops: Observable<Array<Shop>> = new Observable<Array<Shop>>();
  shopId: Subject<Number> = new Subject<Number>();
  currentShop: Observable<Shop> = new Observable<Shop>();

  public static getShopById(shops: Array<Shop>, shopId: Number): Shop {
    return shops.filter(shop => shop.shopId === shopId)[0];
  }
  public static compareShops(oldShop: Shop, newShop: Shop): Boolean {
    return oldShop.shopId === newShop.shopId;
  }

  constructor(@Inject(Http) private http: Http) {
    this.shops = this.http
      .get('**url here**')
      .map(res => res.json().shops);

    this.currentShop = this.shops
      .combineLatest(this.shopId, ShopService.getShopById)
      .distinctUntilChanged(ShopService.compareShops);
  }

  setCurrentShop(shopId: Number): void {
    this.shopId.next(shopId);
  }
}

Component中的用法:

  • ShopService.currentShop保存到Component中的变量(让我们说this.currentShop
  • {{ currentShop | async }}.subscribe()用于ShopService.currentShop观察,以便在商店发生变化时获得商店

查看CodePen上的工作示例。我更喜欢这种方法,因为我没有保存任何状态,这似乎更符合反应式编程。

答案 1 :(得分:1)

我建议如下:

<强> ShopProvider

private shopsObserver:Observer<Shop[]>;
private currentShopObserver: Observer<Shop>;
private _shopDataStore : {
    shops: [],
    currentShop: undefined
}

constructor(http:Http){
    this._http = http;
    this.shops = new Observable(observer => this.obServer = observer).share();
    this.currentShop = new Observable(observer => this.shopObserver = observer).share();

}

setCurrentShop(shopId:number){
   var item = this._shopDataStore.shops.find(item=>item.shopId == shopId);
   this._shopDataStore.currentShop = item;
   this.currentShopObserver.next(this._shopDataStore.currentShop);
}

loadShops(){
    this._http
        .get('/services/shop/list')
        .map(res => res.json())
        .subscribe(data => {
            this._shopDataStore.shops = data;
            this.shopsObserver.next(this._shopDataStore.shops);                
        })
}

<强> AppComponent

export class AppComponent {

    currentShop;
    shopList;

    constructor(router: Router,shopProvider:ShopProvider){
        shopProvider.shops.subscribe(shops=>this.shopList = shops);
        shopProvider.currentShop.subscribe(currentShop => this.currentShop = currentShop);

        shopProvider.loadShops();
        shopProvider.setCurrentShop(-1);

        router.navigate(['/System']);
    }
}

<强> HTML

<div>{{currentShop?.name}}</div>

<ul>
    <li *ngFor="#shop of shopList">
        <a [routerLink]="['/Shop', {shopId: shop.id}]">
            <span>{{shop.name}}</span>
        </a>
    </li>
</ul>