【问题标题】:Getting multiple items out of this.router.events.subscribe()从 this.router.events.subscribe() 中获取多个项目
【发布时间】:2017-07-29 05:19:26
【问题描述】:

我目前正在订阅路由器事件以在路由更改时更改页面的标题,就像这样

this.routerSub$ = this.router.events
    .filter(event => event instanceof NavigationEnd)
    .map(() => this.activatedRoute)
    .map(route => {
        while (route.firstChild) route = route.firstChild;
        return route;
    })
    .filter(route => route.outlet === 'primary')
    .mergeMap(route => route.data)
    .subscribe((event) => {
        title = event['title']
            ? `${event['title']}`
            : 'Default Title'
        this.title.setTitle(title);
    });

我的问题是,在某些情况下,我想将标题设置为 url 中的值(路由的一部分)。我该怎么做?我知道我不能订阅 url 以及事件,但很难弄清楚要在里面映射什么。

这是我正在尝试但失败的方法

   this.router.events
        .filter(event => event instanceof NavigationEnd)
        .map(() => {
            return this.activatedRoute
        })
      .switchMap(route => {
        return route.data.combineLatest(route.url, (data, url) => {
            return data['title'] ? `Title: ${data['title']}` : url.join('');
        });
    })

在 .switchMap 行上,路由的类型为 ActivatedRoute,route.data 的类型为 Object,而我在 combineLatest() 行上遇到的错误是

route.data.combineLatest 不是函数

【问题讨论】:

  • 您的意思是要同时观察eventsurl 并以某种方式组合它们的值?如果是这样,combineLatestwithLatestFrom 会有所帮助。
  • 感谢您指出正确的方法。所以我基本上创建了一个任何对象并将事件和 url 作为道具分配给它?也许一个小样本会帮助我

标签: angular rxjs


【解决方案1】:

如果我们不考虑角度路由细节,您基本上是想组合来自两个不同流的值。至少有几种方法可以做到这一点。

案例 1。您希望在任一流发出时更新标题并使用两者中的最新值。

使用combineLatest:

const getTitle$ = (activatedRoute) => {
    return activatedRoute.url
        .combineLatest(activatedRoute.data, (url, data) => {
            return url + data;
        });
};

const url = Rx.Observable.interval(400).take(3).map(x => `url_${x} `);
const data = Rx.Observable.interval(200).take(6).map(x => `data_${x}`);

getTitle$({ url, data }).subscribe(title => console.log(title));
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>

案例 2。您只想在url 流发出时更新标题,但也从data 流中获取最新值。

使用withLatestFrom:

const getTitle$ = (activatedRoute) => {
    return activatedRoute.url
        .withLatestFrom(activatedRoute.data, (url, data) => {
            return url + data;
        });
}

const url = Rx.Observable.interval(400).take(3).map(x => `url_${x} `);
const data = Rx.Observable.interval(200).take(6).map(x => `data_${x}`);

getTitle$({ url, data }).subscribe(title => console.log(title));
<script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script>

如果你发现你的 observable 不包含任何这些操作符,尝试显式地导入它们:

import 'rxjs/add/operator/combineLatest';
import 'rxjs/add/operator/withLatestFrom';

更新:

为了更具体,这里有一个更接近原始示例的代码示例:

this.router.events
    .filter(event => event instanceof NavigationEnd)
    ... // <- route mapping and filtering skipped for brevity
    .switchMap(route => {
        return route.data.combineLatest(route.url, (data, url) => {
            // make the title out of data and url
            return data['title'] ? `Title: ${data['title']}` : url.join('');
        });
    })
    .subscribe(title => this.title.setTitle(title));

【讨论】:

  • 谢谢你,但我还是有点失落。我需要以某种方式从 this.activatedRoute 获取多个属性(数据和 url)。我正在尝试在该链中合并 combineLatest 并收到类型错误。我需要为数据创建一个常量,为网址创建一个常量,然后合并它们吗?
  • 您能否详细说明您遇到的类型错误以及您的代码是什么样的? ActivatedRoute 中的 dataurl 似乎都是可观察的,但具有不同的元素类型。您可以在传递给combineLatest 的投影函数中按照您需要的方式组合这些值,即签名看起来像combineLatest(Observable&lt;UrlSegment[]&gt;, Observable&lt;Data&gt;, (UrlSegment[], Data) =&gt; String)
  • 我用另外两个代码示例更新了答案,我试图使其更具体。
  • 得到一个错误,说 route.data.combineLatest 不是一个函数。看起来 route.data 已经解析,因此您无法对其执行 Observable 功能。
  • 我想知道,这怎么可能?在您的原始示例中,有一行 .mergeMap(route =&gt; route.data),因此要使该代码工作 route.data 必须是 ObservableArrayPromiseAngular docs 说它一个可观察的。或者route 可以是AngularRouteShanshot 类型吗?你能检查一下类型吗?顺便说一句,如果确实解决了data,那么就更容易了,您不必合并流,只需使用data
猜你喜欢
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-06
  • 1970-01-01
相关资源
最近更新 更多