ionic2+Angular 依赖注入之Subject ——使用Subject来实现组件之间的通信

在Angular+ionic2 开发过程中,我们不难发现,页面之间跳转之后返回时是不会刷新数据的。

场景一:当前页面需要登录之后才能获取数据——去登录,登录成功之后返回——页面需要手动刷新才能获取到数据。

场景二:当前正在浏览地址列表——选择添加或者更改现有地址,保存成功之后——返回列表,页面数据不是最新的数据。

……

实现需求:一旦用户登录成功,列表数据发生变化……就通知相关的组件,主动去获取最新的数据。

类似的场景有很多,在Angular开发中我们就需要使用Subject来实现组件之间的通信。

step1:创建主题对象。为了便于维护和管理,我把项目中需要通信的对象统一声明在一个文件中。

import { UserModel } from '../model-res/user-model';
import { Subject } from "rxjs/Rx";
export const AppOnChangeSunject = {
    UserOnChange: new Subject<UserModel>(),//订阅用户登录状态的变化
    OrderAddressOnChange:new Subject<any>(),//订阅订单地址是否发生改变
    AddressListOnChange:new Subject<any>(),//订阅地址列表数据的更新
}

step2:在相关的数据更新接口中调用next()方法,通知相关的订阅者已经接受到新的信息,以地址列表为例。

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { URLService } from '../../common/urls';
import { EditAddressModel } from '../../model-req/edit-address-model';
import { AppOnChangeSunject } from '../../common/change-subject';

@Injectable()
export class JfAddressService {

    constructor(private http: Http, private us: URLService) { }

    getUserAddress(): Observable<any> {
        let url = this.us.getUrl('yxt_getUserAddress')
        return this.http.get(url).map(res => res.json().data);
    }

    deleteUserAddress(obj): Observable<any> {
        // 删除地址
        let url = this.us.getUrl('yxt_deleteUserAddress', obj);
        return this.http.delete(url, obj).map(res => {
            AppOnChangeSunject.AddressListOnChange.next(200);
            return res.json();
        })
    }

    editUserAddress(obj: EditAddressModel): Observable<any> {
        // 编辑更新地址
        let url = this.us.getUrl('yxt_editUserAddress', obj);
        var data = this.us.objectToUrlParams(obj);
        return this.http.put(url, data).map(res => {
            AppOnChangeSunject.AddressListOnChange.next(200);
            return res.json();
        })
    }

    addUserAddress(obj: EditAddressModel): Observable<any> {
        // 添加地址
        let url = this.us.getUrl('yxt_addUserAddress', obj);
        var data = this.us.objectToUrlParams(obj);
        return this.http.post(url, data).map(res => {
            AppOnChangeSunject.AddressListOnChange.next(200);
            return res.json();
        })
    }

    setUserDefaultAddress(obj):Observable<any>{
        // 设为默认地址
        let url=this.us.getUrl('yxt_setUserDefaultAddress',obj);
        return this.http.post(url,null).map(res=>{
            AppOnChangeSunject.AddressListOnChange.next(200);
            return res.json();
        })
    }

}

 以上的所有操作都会让地址列表的数据发生变化,所以在操作完相关操作之后需要发出通知。

step3:在地址列表组件中添加订阅。

import { Component, OnInit } from '@angular/core';
import { IonicPage, NavController, NavParams, AlertController } from 'ionic-angular';
import { JfAddressService } from '../jf-address.service';
import { AppOnChangeSunject } from '../../../common/change-subject';
import { MsgBarService } from '../../../common/msg-bar';
import { MainPage } from '../../../common/main';
import { WechatService } from '../../../common/wechat.service';


@IonicPage({
  name: 'jfAddress',
  segment: 'jfAddress/:p0',
  defaultHistory:['usercenter']
})
@Component({
  selector: 'page-jf-address',
  templateUrl: 'jf-address.html',
})
//p0订单已选地址
export class JfAddressPage extends MainPage implements OnInit {
  addresses: any[];
  currentAddress;
  constructor(
    public navCtrl: NavController,
    public navParams: NavParams,
    private service: JfAddressService,
    private alertCtrl: AlertController,
    private ms: MsgBarService,
    public wechat: WechatService) {
      super(wechat);
    this.currentAddress = navParams.data.p0 || '';
    AppOnChangeSunject.AddressListOnChange.subscribe(res => {
      if (res == 200) {
        this.getUserAddress();//重新获取最新的数据
      }
    })

  }
  ngOnInit() {
    this.getUserAddress();
  }

  getUserAddress(e?) {
    this.service.getUserAddress().subscribe(res => {
      if (res.addressWsDTOList) {
        this.addresses = res.addressWsDTOList;
      }
      if (e) { e.complete(); }
    },()=>{
      if (e) { e.complete(); }
    })
  }
}

over!