繁体   English   中英

为什么 oninput 事件在 Angular 中的行为与在 JavaScript 中的行为不同?

[英]Why does the oninput event behave differently in Angular than it does in JavaScript?

我正在学习 Angular 和 TypeScript,与 JavaScript 的一些不一致让我感到不安。 这是一个 function 与纯 JavaScript 完美配合(它以编程方式设置输入的minmax属性 - 请不要问我为什么我想以编程方式这样做):

 function change_number(input,min,max) { if(input.value > max) input.value = max; else if(input.value < min) input.value = min; }
 <input type='number' oninput='change_number(this,1,5)' placeholder='Enter a number' />

In Angular and TypeScript, the function behaves strangely: If I enter 10 into the input field, it doesn't reset to 5 , until I enter another digit, meaning the value is only read after the input event (and not on -input -不知道这是否有意义)。 更奇怪的是它与keydownkeyup事件配合得很好。 为什么会有这种行为? 它是否与 Angular 将事件绑定到输入的方式相关联? 我有一种感觉,理解这将有助于我更好地理解 Angular 与NgModel的绑定机制

仅供参考,这是我在 Angular 中调用 function 的方式(使用 Ionic 框架) - 我使用[(ngModel)]中的绑定quantity作为输入值:

<ion-input type='number' (input)='change_numbers(1,5)' [(ngModel)]='quantity'></ion-input>

Angular 框架表现得非常完美 是我们有点糊涂。

Angular 处理 forms 的方式略有不同。 有两种方法可以在 angular 中构建 forms -

  • 反应式(同步)
  • 模板驱动(异步)

它们之间的主要区别在于上述Sync/async 行为 简单来说,我们可以这么说。

  • 同步 - 在数据更改期间。
  • 异步 - 数据更改后。

X

<ion-input type='number' (input)='change_numbers(1,5)' [(ngModel)]='quantity'></ion-input>

以上是一种模板驱动的方法。 这里我们使用[(ngModel)] ,仅在数据更改后才会更新。

为了制作反应输入字段,请使用以下代码:-

在 app.component.ts 文件中

import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

@Component({
  selector: 'dd-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  form: FormGroup;
  min = 0;
  max = 5;

  constructor(private fb: FormBuilder) {
    this.buildForm();
  }

  buildForm(): void {
    this.form = this.fb.group({
      numberInput: ''
    });

    this.form.get('numberInput').valueChanges.pipe(distinctUntilChanged()).subscribe(_ => {
      if (_) {

        if (_ > this.max) {
          this.form.get('numberInput').setValue(5);
        }
        if (_ < this.min) {
          this.form.get('numberInput').setValue(0);
        }

      } else {
        this.form.get('numberInput').reset('');
      }
    });
  }
}

在 app.html 中(这里我发布了 2 种表达方式。)

  <form [formGroup]="form">
    <!-- <input type='number' [min]='0' [max]='5' formControlName="numberInput" /> we can also this one, more easy just set value dynamically -->
    <input type='number' formControlName="numberInput" />
  </form>

注意:- 不要忘记导入ReactiveFormsModule

更多关于 forms 的信息可以在官方文档中找到:-https://angular.io/guide/forms-overview

要理解它为什么会这样,首先你需要熟悉两个基本概念:

  1. “盒子里的香蕉”语法[(ngModel)]="quantity"只不过是被翻译成[ngModel]="quantity" (ngModelChange)="quantity = $event"的糖语法
  2. 在 angular 中,默认情况下会在调用堆栈的末尾触发更改检测(这可以通过 zone.js 实现)。

有了这些知识,您就可以了解这里真正发生了什么:

堆栈闪电战

  1. 您在输入中键入 4。
  2. onNgModelChange被触发, quantity设置为4 input的内部model值(更具体地说, ngModel指令)仍然等于undefined
  3. change_numbers被调用, quantity不变。
  4. 这是调用堆栈的结尾(请注意,由于 angular 处理事件的方式, ngModelChangechange_numbers都在单个调用堆栈中调用)。 执行变化检测。 因为quantity (现在4 )绑定到ngModel (现在undefined ),所以 angular 检测到需要更新 UI(因为undefined != 4当然)。
  5. 执行更新,一切都按预期工作。

  1. 您键入下一个数字 - 8
  2. onNgModelChange被触发, quantity设置为48 input (更具体地说, ngModel指令)的内部model值仍然等于4
  3. change_numbersquantity更改为5
  4. 这是调用堆栈的结尾。 执行变化检测。 因为quantity (现在5 )绑定到ngModel (现在4 ),所以 angular 检测到需要更新 UI(因为5 != 4当然)。
  5. 执行更新,一切都按预期工作。

  1. 您键入下一个数字 - 7
  2. onNgModelChange被触发, quantity设置为57 input (更具体地说, ngModel指令)的内部model值仍然等于5
  3. change_numbersquantity更改为5
  4. 这是调用堆栈的结尾。 执行变化检测。 因为quantity (现在5 )绑定到ngModel (现在也是5 ),所以 angular 没有检测到需要更新 UI(因为5 == 5当然)。
  5. 未执行更新,UI 保持陈旧。

一个解决方案可能是在onNgModelChange方法中调用detectChanges 它会起作用,因为此时我们将更新ngModel的内部model值(即使它远高于5 )。 因此,即使我们接下来将值减小到5 ,angular 仍然会检测到需要更新 UI。

我希望这能解释一切。 如果您有一些问题,请随时告诉我。 干杯!

试试这个,效果很好,如果这不是你想要实现的,请告诉我

堆栈闪电战

html

<input type='number' (change)='change_numbers(1,5)' [(ngModel)]="quantity">

javascript

  change_numbers(min,max) {
   if(this.quantity > max)
     this.quantity = max;
   else if(this.quantity < min)
     this.quantity= min;
 }

不确定这是否有帮助,但我找到了这些;

如何在 Angular 中使用 oninput?

oninput 在 Angular 中不起作用。 选择?

他们似乎经常谈论使用(input) 如果你尝试过?

在谷歌上阅读有关此问题的信息,似乎如果您使用的是 Angular,您必须执行“ Angular 方式”或奇怪的事情,例如您试图寻找答案的事情。

正如 Mandolorian 的 Kuiil 所说; “就是这样”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM