我尝试使用Angular 5实现一个小型翻译工具。我们的想法是从模板中调用一个方法,该方法将从动态生成的翻译列表中翻译字符串。
在下面的代码中,虽然正在调用map运算符,但字符串未显示。
// NOT WORKING
@Component({
selector: 'app-translate',
template: '<h1>{{translate("Takeaway") | async}}</h1>'
})
export class TranslateComponent {
private translateChange = new Subject<any>();
private translateChange$;
constructor() {
this.translateChange$ = this.translateChange.asObservable();
setTimeout(() => {
this.translateChange.next({
'Takeaway': 'To go'
});
}, 1000);
}
translate(str: string) {
return this.translateChange$.map((nameList) => {
return nameList.str || str;
});
}
}
有趣的是,如果我删除了map运算符并将字符串直接传递给Subject,如下所示,那么字符串就会显示出来。
// WORKING
@Component({
selector: 'app-translate',
template: '<h1>{{translate("Takeaway") | async}}</h1>'
})
export class TranslateComponent {
private translateChange = new Subject<any>();
private translateChange$;
constructor() {
this.translateChange$ = this.translateChange.asObservable();
setTimeout(() => {
this.translateChange.next('To go');
}, 1000);
}
translate(str: string) {
return this.translateChange$;
}
}
我想知道为什么.map
运算符与async
管道不匹配,以及是否有更好的方法来实现上述目标。
谢谢!
答案 0 :(得分:0)
所以我在你的例子中看到了一些似乎有点不对劲的事情。
重用现有库
我不明白你为什么要在这里重新发明轮子。有多个转换库已经可以与angular一起使用。我建议您查看ngx-translate,看看它是否符合您的需求。
但是如果你还想建立自己的,还有其他一些东西。
<强>主题强>
我最好的猜测是,这是你的问题的原因。异步管道不纯,因此需要在每个变更检测周期重新评估。在您首次发出主题之前,它不会显示任何内容。在您发出一个值之后,只需一个额外的周期就可以再次停止订阅。
尝试使用BehaviorSubject。当设置新值时,主题将仅发出一次。 BehaviorSubject将始终发出已设置的最后一个值,您需要提供初始值。现在假设您的模板中有一个由* ngIf隐藏的块。在1000毫秒后(您在构造函数中执行的操作),主题将发出一个值。如果在发生这种情况后在* ngIf块中显示一个部分,它将永远不会收到值。
使用BehaviorSubject,将使用最后一个发射的值,因此在这种情况下你应该没问题。
通过组件中的方法提供功能
我认为通过组件中的方法提供翻译并不是一个好主意。如果要在任何其他组件中使用翻译,则需要创建翻译方法。我宁愿去自定义管道。
ngx-translate这样做很好:
{{ 'translationKey' | translate }}
您可以在每个组件中使用它。
我可能会创建一个翻译服务,它负责跟踪活动的翻译(基本上,翻译服务保存translations$
可观察的)和一个将服务作为depdendency的管道,并进行实际的映射从翻译词典到翻译的价值。如果您决定走这条路线,请确保管道标记为不纯。
区别直到更改
我可能会在地图运算符后面添加一个distsinctUntilChanged()
运算符。您只想在值发生变化时发出值。您可以更改包含翻译的对象,但保持一些值保持不变。对于这种情况,您不需要再次发射。