web-dev-qa-db-ja.com

VueJS:「入力」イベントハンドラー内で「入力」イベントをトリガーする理由

私はVueJSを学んでいます。私は彼らの通貨検証を理解しています サンプルコード

Vue.component('currency-input', {
  template: `
    <span>
      $
      <input
        ref="input"
        v-bind:value="value"
        v-on:input="updateValue($event.target.value)">
    </span>
  `,
  props: ['value'],
  methods: {
    // Instead of updating the value directly, this
    // method is used to format and place constraints
    // on the input's value
    updateValue: function (value) {
      var formattedValue = value
        // Remove whitespace on either side
        .trim()
        // Shorten to 2 decimal places
        .slice(
          0,
          value.indexOf('.') === -1
            ? value.length
            : value.indexOf('.') + 3
        )
      // If the value was not already normalized,
      // manually override it to conform
      if (formattedValue !== value) {
        this.$refs.input.value = formattedValue
      }
      // Emit the number value through the input event
      this.$emit('input', Number(formattedValue))
    }
  }
})

UpdateValue関数の下部にある$ emit呼び出しは、入力イベントをトリガーします。

コメントアウトすると、リアルタイムの通貨検証が機能しなくなります。だから私はそれが目的を持っていることを理解しています。

しかし、なぜ入力イベント内で入力イベントをトリガーするのでしょうか。

入力イベントが再び発生し、updateValueハンドラーが再び発生し、再帰呼び出しによるスタックオーバーフローが発生すると考えられます。

VueJSのはるかに単純な$ emitサンプルコードを理解しています。それはちょうどJqueryのトリガー関数のようなものです。

vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')
// -> "hi"

しかし、通貨検証の例では、$ emitがなぜそれと同じように使用され、なぜそれがどのように機能するのか理解できません。

誰かが説明できますか?

9
Jay

ここでのEmit呼び出しは、親コンテキストでイベントにフックできるようにするためのものです。 Inputイベントは、コンポーネントとの双方向バインディングを処理するために_v-model_ディレクティブでも使用されます。

_v-model='model'_は、基本的に_v-bind:value='model' v-on:input='model = $event.target.value'_であり、ニースを再生するためにいくつかのビットが追加されています。 this.$emit('input', Number(formattedValue))を削除すると、コンポーネント外の値を更新するメカニズムが削除されます。

編集:@Jayは時々あなたが望むものを注意してください

HTMLのすべての要素には、一般的なイベント用の一連のネイティブハンドラーがあります。サイズ変更、ロード、アンロードなど。これらは、ページのレンダリングが変更されたときに何を行うかを処理し、JavaScriptブラウザーの導入により、複数の関数を任意のイベントにアタッチできるイベントポンプシステムを使用しているため、無効化または追加できます。イベントが発生したときに順番に実行されます。最小/最大サイズ、画面の向きなどのEdgeケースを処理するために、サイズ変更で3つの関数を実行する方法の例です。

フォーム要素は通常、独自の基本イベント関数(keydown、keyup、mousedown、mouseup)を実装します。これらの基本関数は、イベントを呼び出して、開発者としての生活を容易にします。入力、ぼかし、フォーカスです。一部の要素には、変更を実装する選択要素、送信を実装するフォームタグなどの特殊なイベントがあります。

フォーカスの入力タグはキーボード入力をキャプチャし、テキスト入力カーソルを表示して、入力を受け取る準備ができていることを示します。次の使用可能な入力を見つけてフォーカスをその要素に移動するタブキーコードのハンドラーを追加します。イベントポンプスタイルの関数システムは、入力をキャプチャしたりカーソルを表示したりするためのコードを実装する必要なく、フォーカスにバインドして、入力がフォーカスされたときに背景色や境界線を変更するなどの操作を実行できるため、優れています。

入力タグは、入力時にinputイベントも発生させ、入力が変更されたことを示し、ユーザーに期待される機能が一貫するように値を変更して表示を更新するようブラウザに指示します。

_currency-input_の例では、updateValue関数を追加してネイティブ関数を処理し、イベントの入力値を処理します。updateValue関数では、価値とそれを置く場所が必要です。単純にデータプロパティを追加して値を保持し、入力の値プロパティをデータプロパティにバインドして、_currency-input_が結果の表示を内部的に処理できるようにしますが、プライベートアクセサーの背後で値をロックします。結果の通貨形式の値の値を変更または取得できません。

this.$emit('input', Number(formattedValue))を使用すると、updateValue関数は、親コンテキストでキャプチャして操作できるイベントを発生させることにより、ネイティブのinputタグと同様に機能します。それを値に保存したり、関数の基礎として使用したり、完全に無視したりすることもできますが、あまり役に立ちません。これにより、入力の値を追跡し、必要に応じて変更したり、サーバーに送信したり、表示したりできます。

また、現在のコンテキスト内のデータプロパティへのvalueプロパティバインディングとinputイベントバインディングを可能にする構文シュガーである_v-model_をいくつかのディレクティブに関連付けます。 valueプロップを提供し、inputイベントを発行することにより、カスタム要素は、Vueアプリケーションのシステムのネイティブフォーム要素と同様に機能できます。コンポーネントをパッケージ化して配布または再利用する場合の魅力的な機能。

行く方がずっといいです:

_...
<currency-input v-model='dollarValue'></currency-input>
<input v-model='dollarValue'>
...
_

Ergoのどこにでもvalueおよびinputバインディングを追加する必要があるより:

_...
<currency-input v-bind:value='dollarValue' v-on:input='updateDollarValue($event.target.value)'></currency-input>
<input v-bind:value='dollarValue' v-on:input='updateDollarValue($event.target.value)'>
...
_

私の奇妙なとりとめができたので、これが_currency-input_の例の背後にあるパターンと推論のいくつかを理解するのに役立つことを願っています。

11