Angular双向数据绑定和监听父组件的变化
Angular Two-Way Data Binding and Watching for Changes in Parent Component
使用双向数据绑定时,似乎无法查看父组件的变化。
我有一个用于收集标签列表的自定义输入组件。双向数据绑定已设置并在此组件与其父组件之间工作。
// the parent component is just a form
// here is how I'm adding the child component
<input-tags formControlName="skillField" [(tags)]='skillTags' (ngModelChange)="skillTagUpdate($event)">
</input-tags>
在父组件中如何观察绑定变量的变化?虽然它始终是最新的(我已经确认了这一点),但我找不到任何关于对变化做出反应的指导。
我试过:
ngOnChanges(changes: SimpleChanges) {
if (changes['skillTags']) {
console.log(this.skillTags); // nothing
}
}
和
skillTagUpdate(event){
console.log(event); // nothing
}
更新:
TWDB 恕我直言,并不是它所宣传的那样。每当我到达这个 TWDB 似乎是解决方案的地方时,我都会重新设计服务和/或可观察通信。
你可以听到变化:
<input-tags formControlName="skillField" [tags]='skillTags' (tagsChange)='skillTags=$event; skillTagUpdate();'></input-tags>
或使用getter和setter:
get skillTags(): string {
return ...
}
set skillTags(value) {
variable = value;
}
另一种方法:
export class Test implements DoCheck {
differ: KeyValueDiffer<string, any>;
public skillTags: string[] = [];
ngDoCheck() {
const change = this.differ.diff(this.skillTags);
if (change) {
change.forEachChangedItem(item => {
doSomething();
});
}
}
constructor(private differs: KeyValueDiffers) {
this.differ = this.differs.find({}).create();
}
}}
1.you 可以使用输出(eventemitter)
2.easiest 解是rxjs/subject。它可以同时被观察者和可观察者
用法:
1.Create 服役对象 属性:
import { Subject } from 'rxjs';
export class AuthService {
loginAccures: Subject<boolean> = new Subject<boolean>();
}
2.When 事件发生在 child page/component 使用:
logout(){
this.authService.loginAccures.next(false);
}
3.And 订阅 parent 中的主题 page/component:
constructor(private authService: AuthService) {
this.authService.loginAccures.subscribe((isLoggedIn: boolean) => {this.isLoggedIn = isLoggedIn;})
}
更新
对于 two-way 绑定,您可以使用视图child 访问您的 child 组件项目和属性
<input-tags #test></<input-tags>
并在 ts 文件中
@ViewChild('test') inputTagsComponent : InputTagsComponent;
save()
{
var childModel = this.inputTagsComponent.Model;
}
不知道这是否是您要找的,但您是否尝试过使用@Input()?
在子组件中
@Input() set variableName(value: valueType) {
console.log(value);
}
在父组件中
<input-tags formControlName="skillField" [(tags)]='skillTags'
[variableName]="skillTagUpdate($event)"></input-tags>
每次更改绑定到函数的对象时都会调用输入函数。
当您实现自己的双向绑定时,您必须实现一个事件发射器。语法是强制性的。
这意味着如果值发生变化,您有一个钩子可以监听。
这是一个演示:
<hello [(name)]="name" (nameChange)="doSomething()"></hello>
_name: string;
@Output() nameChange = new EventEmitter();
set name(val) {
this._name = val;
this.nameChange.emit(this._name);
}
@Input()
get name() {
return this._name;
}
counter = 0;
ngOnInit() {
setInterval(() => {
this.name = this.name + ', ' + this.counter++;
}, 1000);
}
据我所知,这似乎是一种不那么烦人的使用方式,无论如何任何双向绑定都将遵循相同的规则,即它以 Change
字结尾!
您的实现实际上不是 two-way 数据绑定,父组件和子组件只是共享对同一个 skillTags
变量的引用。
语法 [(tags)]='skillTags'
是 [tags]='skillTags' (tagsChange)='skillTags = $event'
的语法糖
你需要在子组件中实现tagsChange
这样:@Output('tagsChange') tagsChange = new EventEmitter<any>();
,那么任何时候你想在子组件中修改tags
,不要直接这样做,但是请改用 this.tagsChange.emit(newValue)
。
此时,您将拥有真正的 two-way 数据绑定,并且父组件是变量的唯一所有者(负责在其上应用更改并将更改广播给子组件)。
现在在你的父组件中,如果你想做的不仅仅是skillTags = $event
(用[(tags)]='skillTags'
隐式完成),那么只需添加另一个监听器(tagsChange)='someFunction($event)'
。
使用双向数据绑定时,似乎无法查看父组件的变化。
我有一个用于收集标签列表的自定义输入组件。双向数据绑定已设置并在此组件与其父组件之间工作。
// the parent component is just a form
// here is how I'm adding the child component
<input-tags formControlName="skillField" [(tags)]='skillTags' (ngModelChange)="skillTagUpdate($event)">
</input-tags>
在父组件中如何观察绑定变量的变化?虽然它始终是最新的(我已经确认了这一点),但我找不到任何关于对变化做出反应的指导。
我试过:
ngOnChanges(changes: SimpleChanges) {
if (changes['skillTags']) {
console.log(this.skillTags); // nothing
}
}
和
skillTagUpdate(event){
console.log(event); // nothing
}
更新: TWDB 恕我直言,并不是它所宣传的那样。每当我到达这个 TWDB 似乎是解决方案的地方时,我都会重新设计服务和/或可观察通信。
你可以听到变化:
<input-tags formControlName="skillField" [tags]='skillTags' (tagsChange)='skillTags=$event; skillTagUpdate();'></input-tags>
或使用getter和setter:
get skillTags(): string {
return ...
}
set skillTags(value) {
variable = value;
}
另一种方法:
export class Test implements DoCheck {
differ: KeyValueDiffer<string, any>;
public skillTags: string[] = [];
ngDoCheck() {
const change = this.differ.diff(this.skillTags);
if (change) {
change.forEachChangedItem(item => {
doSomething();
});
}
}
constructor(private differs: KeyValueDiffers) {
this.differ = this.differs.find({}).create();
}
}}
1.you 可以使用输出(eventemitter)
2.easiest 解是rxjs/subject。它可以同时被观察者和可观察者
用法:
1.Create 服役对象 属性:
import { Subject } from 'rxjs';
export class AuthService {
loginAccures: Subject<boolean> = new Subject<boolean>();
}
2.When 事件发生在 child page/component 使用:
logout(){
this.authService.loginAccures.next(false);
}
3.And 订阅 parent 中的主题 page/component:
constructor(private authService: AuthService) {
this.authService.loginAccures.subscribe((isLoggedIn: boolean) => {this.isLoggedIn = isLoggedIn;})
}
更新
对于 two-way 绑定,您可以使用视图child 访问您的 child 组件项目和属性
<input-tags #test></<input-tags>
并在 ts 文件中
@ViewChild('test') inputTagsComponent : InputTagsComponent;
save()
{
var childModel = this.inputTagsComponent.Model;
}
不知道这是否是您要找的,但您是否尝试过使用@Input()?
在子组件中
@Input() set variableName(value: valueType) {
console.log(value);
}
在父组件中
<input-tags formControlName="skillField" [(tags)]='skillTags'
[variableName]="skillTagUpdate($event)"></input-tags>
每次更改绑定到函数的对象时都会调用输入函数。
当您实现自己的双向绑定时,您必须实现一个事件发射器。语法是强制性的。
这意味着如果值发生变化,您有一个钩子可以监听。
这是一个演示:
<hello [(name)]="name" (nameChange)="doSomething()"></hello>
_name: string;
@Output() nameChange = new EventEmitter();
set name(val) {
this._name = val;
this.nameChange.emit(this._name);
}
@Input()
get name() {
return this._name;
}
counter = 0;
ngOnInit() {
setInterval(() => {
this.name = this.name + ', ' + this.counter++;
}, 1000);
}
据我所知,这似乎是一种不那么烦人的使用方式,无论如何任何双向绑定都将遵循相同的规则,即它以 Change
字结尾!
您的实现实际上不是 two-way 数据绑定,父组件和子组件只是共享对同一个 skillTags
变量的引用。
语法 [(tags)]='skillTags'
是 [tags]='skillTags' (tagsChange)='skillTags = $event'
你需要在子组件中实现tagsChange
这样:@Output('tagsChange') tagsChange = new EventEmitter<any>();
,那么任何时候你想在子组件中修改tags
,不要直接这样做,但是请改用 this.tagsChange.emit(newValue)
。
此时,您将拥有真正的 two-way 数据绑定,并且父组件是变量的唯一所有者(负责在其上应用更改并将更改广播给子组件)。
现在在你的父组件中,如果你想做的不仅仅是skillTags = $event
(用[(tags)]='skillTags'
隐式完成),那么只需添加另一个监听器(tagsChange)='someFunction($event)'
。