簡體   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