http://jsfiddle.net/2NJ7y/3/ (AngularJS 1.0.1 のバージョン) の例を見てください。ラッキーナンバーの入力を待つシンプルなアプリがあります。数字が 7 の場合、ラッキー ナンバーを null にリセットします。数字の 7 を数回入力すると、時々/ランダムにラッキー ナンバーが入力フィールドに残ります。なんで?この動作はどのように解決しますか? ありがとう。
3 に答える
私はいくつかのデバッグを行いました。
まず、ラッキーナンバーはランダムではなく入力フィールドにとどまります。
enter 3 (model==3, input==3)
=>enter 7 (alert, model==null, input="")
=> enter 3 (model==3, input==3)
=>remove 3 (model=="", input=="")
=>enter 7 (alert, model==null, input="")
=>enter 7 (alert, model==null, input="7")
7 前のモデル値が null の場合にのみ、入力フィールドに留まります。
何が起こるか:入力ディレクティブのリスナー関数によって処理される 7 起動された入力イベントを入力すると。リスナー関数は$setViewValueを呼び出します。$setViewValue は $viewValue、$modelValue、モデル値を設定し、$viewChangeListeners を呼び出します (ngChangeDirective は $viewChangeListenersにハンドラを追加するだけです)。アラートが表示され、ラッキーナンバーが null に設定されます。結局、luckynumber が以前のダーティ チェックで以前の値と異なる場合、$watch ハンドラと$renderが呼び出されます。
私の例では、前のモデル値が「3」または「」の場合に $render が呼び出されました。前のモデルの値が null の場合、$render は呼び出されません。
$timeout with 0 delay が機能する理由: 0 delay 関数を指定して $timeout を呼び出し、luckynumber を null に変更すると、イベント キューの最後で延期されます(ブラウザー内のすべての JavaScript は単一のスレッドで実行されます)。$viewChangeListener はモデル値を 7 から null に変更しません。$digest が終了します。次に、$timeout ハンドラが呼び出されます。モデル値が null に設定されています。$watch ハンドラと $render が呼び出されます。$render は入力値を "" に設定します。
ついに、解決策。ng-change の代わりに $watch を使用します。
$scope.$watch('luckynumber', function() {
if ($scope.luckynumber == 7) {
alert('The lucky number mustn\'t be equal 7.');
$scope.luckynumber = null;
}
})
フィドル。
@Valentynによるこの他のSOの回答により、この質問に対するその解決策を試すことを考えさせられました。
簡単に言えば
$scope.luckynumber = undefined;
アラートの前に競合状態を排除しませんが、7 が適切にクリアされるように変更しますが、アラートが 2 回発生することがあります。
エラーを表示するように DOM を変更するなど、アラート コードがべき等なものに置き換えられた場合、この問題は重要ではなくなります。