【问题标题】:Angular2+: how does NgModel / NgControl internally handle updates from view to model?Angular2+:NgModel / NgControl 如何在内部处理从视图到模型的更新?
【发布时间】:2018-08-24 07:37:28
【问题描述】:

我正在深入研究双向数据绑定的工作原理。我目前对来自视图的更新(例如,input 元素)如何在内部传播到 NgControl 感到困惑。

ControlValueAccessor 的定义中提到registerOnChange 负责视图-> 模型更新(docs where they say itsrc)。使用一个简单的指令,我们可以将相同的input 元素与[(NgModel)] 放在一起,例如<input [(NgModel)]=stuff myInspectorDirective>,我试着玩弄这个。

constructor(private ngControl: NgControl) { }
ngOnInit(): void {
    // this.ngControl.valueAccessor['onChange'] = () => {}; 
    // uncommenting the above line prevents updates from view to model 
}

取消注释/注释指示的行允许我们允许/阻止从输入元素到模型的更新。但我对此感到困惑,因为在DefaultValueAccessor 的源代码中,本示例中使用的onChange 并没有真正做任何事情:(_:any) => {}

所以,我希望在引擎盖下,例如在ng_model.ts 或相关类之一中,如NgControlFormControl,ValueAccessor 中的onChange 函数会发生某些事情;设置它或将其包装在另一个函数中,也许是代理,或者其他什么。我什么也没找到。然后我继续寻找一些代码,其中侦听器(对于input 事件,更明确)明确绑定到输入元素,但也没有运气。

我注意到OnChanges function calls _setValue,但我不确定在深入研究更改检测的内部时我是否朝着正确的方向前进,因为我希望侦听 DOM 中的更改与ControlValueAccessors 和/或 FormControl/AbstractControl

有人想详细说明这是如何工作的吗? :-)

【问题讨论】:

    标签: javascript angular typescript angular2-directives angular2-ngmodel


    【解决方案1】:

    ControlValueAccessor.registerOnChange 由 NgForm 提供。

    1) NgModel 在 NgForm 中注册(见https://github.com/angular/angular/blob/master/packages/forms/src/directives/ng_model.ts

    in NgModel.ngOnChanges: this._setUpControl calls this.formDirective.addControl
    

    2) NgForm 调用共享的 setUpControl 函数(见https://github.com/angular/angular/blob/master/packages/forms/src/directives/ng_form.ts

    import { setUpControl } from './shared';
    NgForm.addControl calls setUpControl
    

    3) setUpControl 注册更改事件处理程序(参见https://github.com/angular/angular/blob/master/packages/forms/src/directives/shared.ts

    setUpControl calls setUpViewChangePipeline
    
    function setUpViewChangePipeline(control: FormControl, dir: NgControl): void {
      dir.valueAccessor !.registerOnChange((newValue: any) => {
        control._pendingValue = newValue;
        control._pendingChange = true;
        control._pendingDirty = true;
    
        if (control.updateOn === 'change') updateControl(control, dir);
      });
    }
    

    【讨论】:

      猜你喜欢
      • 2016-05-24
      • 2016-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      • 2019-05-25
      • 1970-01-01
      相关资源
      最近更新 更多