在AngularJS中,你可以使用$scope的$watch函数指定观察者来观察作用域变量的变化。在Angular中,什么与监视变量变化(比如组件变量)是等价的?
当前回答
这并没有直接回答这个问题,但我在不同的情况下遇到过这个Stack Overflow问题,以解决我在angularJs中使用$watch的问题。我最终使用了另一种方法,而不是目前的答案中所描述的方法,并且想要分享它,以防有人发现它有用。
我用来实现类似$watch的技术是在Angular服务中使用一个BehaviorSubject(这里有更多关于这个主题的内容),并让我的组件订阅它,以便获得(监视)更改。这类似于angularJs中的$watch,但需要更多的设置和理解。
在我的组件中:
export class HelloComponent {
name: string;
// inject our service, which holds the object we want to watch.
constructor(private helloService: HelloService){
// Here I am "watching" for changes by subscribing
this.helloService.getGreeting().subscribe( greeting => {
this.name = greeting.value;
});
}
}
为我服务
export class HelloService {
private helloSubject = new BehaviorSubject<{value: string}>({value: 'hello'});
constructor(){}
// similar to using $watch, in order to get updates of our object
getGreeting(): Observable<{value:string}> {
return this.helloSubject;
}
// Each time this method is called, each subscriber will receive the updated greeting.
setGreeting(greeting: string) {
this.helloSubject.next({value: greeting});
}
}
这是一个关于Stackblitz的演示
其他回答
这个行为现在是组件生命周期的一部分。
组件可以在OnChanges接口中实现ngOnChanges方法来访问输入更改。
例子:
import {Component, Input, OnChanges} from 'angular2/core';
@Component({
selector: 'hero-comp',
templateUrl: 'app/components/hero-comp/hero-comp.html',
styleUrls: ['app/components/hero-comp/hero-comp.css'],
providers: [],
directives: [],
pipes: [],
inputs:['hero', 'real']
})
export class HeroComp implements OnChanges{
@Input() hero:Hero;
@Input() real:string;
constructor() {
}
ngOnChanges(changes) {
console.log(changes);
}
}
如果你想让它双向绑定,你可以使用[(yourVar)],但你必须实现yourVarChange事件,并在每次变量改变时调用它。
像这样的东西来跟踪英雄的变化
@Output() heroChange = new EventEmitter();
然后当你的英雄发生变化时,调用this.heroChange.emit(this.hero);
[(英雄)]绑定将为您完成其余的工作
请看例子:
http://plnkr.co/edit/efOGIJ0POh1XQeRZctSx?p=preview
在Angular 2中,变更检测是自动的…$scope.$watch()和$scope.$digest()安息吧
不幸的是,开发指南的变更检测部分还没有编写出来(在架构概述页面底部的“其他东西”部分有一个占位符)。
以下是我对变更检测工作原理的理解:
Zone.js "monkey patches the world" -- it intercepts all of the asynchronous APIs in the browser (when Angular runs). This is why we can use setTimeout() inside our components rather than something like $timeout... because setTimeout() is monkey patched. Angular builds and maintains a tree of "change detectors". There is one such change detector (class) per component/directive. (You can get access to this object by injecting ChangeDetectorRef.) These change detectors are created when Angular creates components. They keep track of the state of all of your bindings, for dirty checking. These are, in a sense, similar to the automatic $watches() that Angular 1 would set up for {{}} template bindings.Unlike Angular 1, the change detection graph is a directed tree and cannot have cycles (this makes Angular 2 much more performant, as we'll see below). When an event fires (inside the Angular zone), the code we wrote (the event handler callback) runs. It can update whatever data it wants to -- the shared application model/state and/or the component's view state. After that, because of the hooks Zone.js added, it then runs Angular's change detection algorithm. By default (i.e., if you are not using the onPush change detection strategy on any of your components), every component in the tree is examined once (TTL=1)... from the top, in depth-first order. (Well, if you're in dev mode, change detection runs twice (TTL=2). See ApplicationRef.tick() for more about this.) It performs dirty checking on all of your bindings, using those change detector objects. Lifecycle hooks are called as part of change detection. If the component data you want to watch is a primitive input property (String, boolean, number), you can implement ngOnChanges() to be notified of changes. If the input property is a reference type (object, array, etc.), but the reference didn't change (e.g., you added an item to an existing array), you'll need to implement ngDoCheck() (see this SO answer for more on this). You should only change the component's properties and/or properties of descendant components (because of the single tree walk implementation -- i.e., unidirectional data flow). Here's a plunker that violates that. Stateful pipes can also trip you up here. For any binding changes that are found, the Components are updated, and then the DOM is updated. Change detection is now finished. The browser notices the DOM changes and updates the screen.
了解更多信息的其他参考资料:
Angular’s $digest is reborn in the newer version of Angular - explains how the ideas from AngularJS are mapped to Angular Everything you need to know about change detection in Angular - explains in great detail how change detection works under the hood Change Detection Explained - Thoughtram blog Feb 22, 2016 - probably the best reference out there Savkin's Change Detection Reinvented video - definitely watch this one How does Angular 2 Change Detection Really Work?- jhade's blog Feb 24, 2016 Brian's video and Miško's video about Zone.js. Brian's is about Zone.js. Miško's is about how Angular 2 uses Zone.js to implement change detection. He also talks about change detection in general, and a little bit about onPush. Victor Savkins blog posts: Change Detection in Angular 2, Two phases of Angular 2 applications, Angular, Immutability and Encapsulation. He covers a lot of ground quickly, but he can be terse at times, and you're left scratching your head, wondering about the missing pieces. Ultra Fast Change Detection (Google doc) - very technical, very terse, but it describes/sketches the ChangeDetection classes that get built as part of the tree
如果除自动双向绑定外,还希望在值更改时调用函数,则可以将双向绑定快捷语法转换为更详细的版本。
<input [(ngModel)]=“yourVar”></input>
是简写
<input [ngModel]=“yourVar” (ngModelChange)=“yourVar=$event”></input>
(参见http://victorsavkin.com/post/119943127151/angular-2-template-syntax)
你可以这样做:
<input [(ngModel)]=“yourVar” (ngModelChange)=“changedExtraHandler($event)”></input>
下面是为模型使用getter和setter函数的另一种方法。
@Component({
selector: 'input-language',
template: `
…
<input
type="text"
placeholder="Language"
[(ngModel)]="query"
/>
`,
})
export class InputLanguageComponent {
set query(value) {
this._query = value;
console.log('query set to :', value)
}
get query() {
return this._query;
}
}
推荐文章
- Angular中相当于AngularJS $watch的东西是什么?
- Angular 2没有base href设置
- AngularJS路由不带散列“#”
- 单击表单中的按钮会刷新页面
- 典型的AngularJS工作流程和项目结构(使用Python Flask)
- 检查已安装的angular-cli版本?
- 在Angular 1.2+中如何使用$sce.trustAsHtml(string)来复制ng-bind-html-unsafe
- Angular ng-repeat反过来
- 盎格鲁- ngcloak / ngg展示blink元素
- Angular:如何在不改变路由的情况下更新queryParams
- 当我通过浏览器刷新时,会出现Angular 2: 404错误
- Angular中的Subject vs behaviour Subject vs ReplaySubject
- Angular 2单元测试:找不到名称“describe”
- 使用AngularJS限制字符串的长度
- 在服务中处理$http响应