简体   繁体   English

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

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

I'm learning Angular with TypeScript, and a few inconsistencies with JavaScript are troubling me.我正在学习 Angular 和 TypeScript,与 JavaScript 的一些不一致让我感到不安。 Here's a function which works perfectly with pure JavaScript (it programmatically sets min and max attributes to an input - please don't ask me why I'd want to do that programmatically ):这是一个 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 - don't know if that makes sense). 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 -不知道这是否有意义)。 What's more strange is it works fine with the keydown and keyup events.更奇怪的是它与keydownkeyup事件配合得很好。 Why this behaviour?为什么会有这种行为? Is it linked to the way Angular binds events to inputs?它是否与 Angular 将事件绑定到输入的方式相关联? I have a feeling understanding this would help me better understand Angular's binding mechanism with NgModel我有一种感觉,理解这将有助于我更好地理解 Angular 与NgModel的绑定机制

FYI, here's how I called the function in Angular (using the Ionic Framework) - I used the bound quantity in [(ngModel)] as the value of the input:仅供参考,这是我在 Angular 中调用 function 的方式(使用 Ionic 框架) - 我使用[(ngModel)]中的绑定quantity作为输入值:

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

Angular framework is behaving perfectly the way it has to . Angular 框架表现得非常完美 It is us who are a bit confused.是我们有点糊涂。

Angular handles forms in a bit different manner. Angular 处理 forms 的方式略有不同。 There are two approaches to build forms in angular -有两种方法可以在 angular 中构建 forms -

  • Reactive (Synchronous)反应式(同步)
  • Template-driven (Asynchronous)模板驱动(异步)

The Key difference between them is the above Sync/async behaviour .它们之间的主要区别在于上述Sync/async 行为 In simple terms we can say that.简单来说,我们可以这么说。

  • Synchronous - during the data change.同步 - 在数据更改期间。
  • Asynchronous - after the data has changed.异步 - 数据更改后。

x X

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

Above one is a Template-driven approach.以上是一种模板驱动的方法。 Here we are using [(ngModel)] , this updates only after the data has changed.这里我们使用[(ngModel)] ,仅在数据更改后才会更新。

In order to make a reactive input field, use below code:-为了制作反应输入字段,请使用以下代码:-

in app.component.ts file在 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('');
      }
    });
  }
}

In app.html (Here i am posting 2 way to express it.)在 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>

NOTE:- DONT FORGET TO IMPORT ReactiveFormsModule注意:- 不要忘记导入ReactiveFormsModule

More about forms can found in the official docs: -https://angular.io/guide/forms-overview更多关于 forms 的信息可以在官方文档中找到:-https://angular.io/guide/forms-overview

To understand why it behaves like that, first you need to be familiar with two basic concepts:要理解它为什么会这样,首先你需要熟悉两个基本概念:

  1. A "banana in the box" syntax [(ngModel)]="quantity" is nothing more than sugar syntax which is translated to [ngModel]="quantity" (ngModelChange)="quantity = $event" “盒子里的香蕉”语法[(ngModel)]="quantity"只不过是被翻译成[ngModel]="quantity" (ngModelChange)="quantity = $event"的糖语法
  2. In angular, change detection is by default triggered at the end of the call stack (this is possible with zone.js).在 angular 中,默认情况下会在调用堆栈的末尾触发更改检测(这可以通过 zone.js 实现)。

With this knowledge, you can understand what really happens here:有了这些知识,您就可以了解这里真正发生了什么:

stackblitz 堆栈闪电战

  1. You type 4 into the input.您在输入中键入 4。
  2. onNgModelChange is triggered, quantity is set to 4 . onNgModelChange被触发, quantity设置为4 The inner model value of input (more specifically, ngModel directive) is still equal to undefined . input的内部model值(更具体地说, ngModel指令)仍然等于undefined
  3. change_numbers is called, quantity is not changed. change_numbers被调用, quantity不变。
  4. This is the end of the callstack (note that ngModelChange and change_numbers all called in a single callstack due to how angular handles events).这是调用堆栈的结尾(请注意,由于 angular 处理事件的方式, ngModelChangechange_numbers都在单个调用堆栈中调用)。 Change detection is performed.执行变化检测。 Because quantity ( 4 now) is bound to the ngModel ( undefined now), angular detects a need to update the UI (because undefined != 4 of course).因为quantity (现在4 )绑定到ngModel (现在undefined ),所以 angular 检测到需要更新 UI(因为undefined != 4当然)。
  5. Update is performed, everything works as expected.执行更新,一切都按预期工作。

  1. You type the next number - 8 .您键入下一个数字 - 8
  2. onNgModelChange is triggered, quantity is set to 48 . onNgModelChange被触发, quantity设置为48 The inner model value of input (more specifically, ngModel directive) is still equal to 4 . input (更具体地说, ngModel指令)的内部model值仍然等于4
  3. change_numbers is called, quantity is changed to 5 . change_numbersquantity更改为5
  4. This is the end of the callstack.这是调用堆栈的结尾。 Change detection is performed.执行变化检测。 Because quantity ( 5 now) is bound to the ngModel ( 4 now), angular detects a need to update the UI (because 5 != 4 of course).因为quantity (现在5 )绑定到ngModel (现在4 ),所以 angular 检测到需要更新 UI(因为5 != 4当然)。
  5. Update is performed, everything works as expected.执行更新,一切都按预期工作。

  1. You type the next number - 7 .您键入下一个数字 - 7
  2. onNgModelChange is triggered, quantity is set to 57 . onNgModelChange被触发, quantity设置为57 The inner model value of input (more specifically, ngModel directive) is still equal to 5 . input (更具体地说, ngModel指令)的内部model值仍然等于5
  3. change_numbers is called, quantity is changed to 5 . change_numbersquantity更改为5
  4. This is the end of the callstack.这是调用堆栈的结尾。 Change detection is performed.执行变化检测。 Because quantity ( 5 now) is bound to the ngModel (also 5 now), angular doesn't detect a need to update the UI (because 5 == 5 of course).因为quantity (现在5 )绑定到ngModel (现在也是5 ),所以 angular 没有检测到需要更新 UI(因为5 == 5当然)。
  5. Update is not performed, UI remains stale.未执行更新,UI 保持陈旧。

A solution to that might be calling detectChanges in onNgModelChange method.一个解决方案可能是在onNgModelChange方法中调用detectChanges It will work, because in this moment we will update the inner model value of ngModel (even if it is much higher than 5 ).它会起作用,因为此时我们将更新ngModel的内部model值(即使它远高于5 )。 So even if we next decrease the value to 5 , angular still will detect a need to update the UI.因此,即使我们接下来将值减小到5 ,angular 仍然会检测到需要更新 UI。

I hope that explains everything.我希望这能解释一切。 If you'll have some questions, don't hesitate to let me know.如果您有一些问题,请随时告诉我。 Cheers!干杯!

Try this out, this works well, let me know if this is not what you want to achieve试试这个,效果很好,如果这不是你想要实现的,请告诉我

stackblitz堆栈闪电战

html html

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

javascript javascript

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

Not sure if this helps, but I found these;不确定这是否有帮助,但我找到了这些;

how to use oninput in Angular? 如何在 Angular 中使用 oninput?

oninput not working in Angular. oninput 在 Angular 中不起作用。 Alternative? 选择?

They seem to talk a lot about using (input) ;他们似乎经常谈论使用(input) if you've tried it?如果你尝试过?

Reading on google about this issue, it just seems like if you're using Angular you have to do things " The Angular Way " or oddities like what you're trying to seek an answer for occur.在谷歌上阅读有关此问题的信息,似乎如果您使用的是 Angular,您必须执行“ Angular 方式”或奇怪的事情,例如您试图寻找答案的事情。

As Kuiil from The Mandolorian says;正如 Mandolorian 的 Kuiil 所说; "This is the way" “就是这样”

暂无
暂无

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

相关问题 为什么jQuery的行为与javascript不同? - Why does jQuery behave differently than javascript? 为什么/ * * /注释的行为不同? Javascript错误? - Why does /* */ comment behave differently ? Javascript bug? 为什么按钮上的侦听器的行为与表单上的侦听器不同(两者都是事件提交) - why does listener on button behave differently than listener on form (both to event submit) Angular 2,带有setter的@Input与没有setter的@Input的行为有什么不同? - Angular 2, Does @Input with a setter behave differently than @Input without a setter? 为什么 || JavaScript 中的 (or) 和 &amp;&amp; (and) 运算符的行为与 C 中的不同(返回非布尔值)? - Why does the || (or) and && (and) operator in JavaScript behave differently than in C (returning non boolean value)? 为什么这个函数表达式的行为与函数声明不同? - Why does this function expression behave differently than a function declaration? 为什么无服务器中的本地事件变量表现不同? - Why does the local event variable in serverless behave differently? 角度形式:为什么指令的行为与类型不同? - Angular-formly: Why does the directive behave differently from the type? 为什么此全局Javascript变量在函数内部和外部的行为有所不同? - Why does this global Javascript variable behave differently inside and outside of a function? 为什么这个javascript对象在有和没有模块模式的情况下表现不同? - Why does this javascript object behave differently with and without a module pattern?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM