angularjsの$watch,$apply,$digestについて
みんなangularJSの中でとてもキックアスの1つの性能で、データは双方向にバインドして、これはviewの中のデータがいかなる変化が発生することを意味して、この変化もそれに応じてscopeの上で反映して、つまりscopeの模型は動態的に更新します.だから、私たちのニーズはモデルの変化を監視することかもしれません.次に、この操作と実現原理を簡単に説明します.
$watch$watchは、モデルの変化を簡単に監視し、栗を挙げることができます.
上のコードはnameの変化を監視するために使用され、input入力ボックスに値を入力するたびに$rootScopeのcountが+1に対応します.
angularJSの内部では、nameの値を変更するたびにangularJSの内部の$digestが呼び出され(以下、$digestの原理を詳細に説明する)、実行終了後に$watchで監視したモデルをチェックし、前回の$digestの実行前と比較してどのように変化したかを確認すると、$watchのコールバック関数が実行されます.
しかし!!我々の実際の開発では、1つの元のタイプのデータモニタリングを実現するだけでは、必要なものをはるかに満たすことができません.元のタイプのデータに対して、1回の付与操作を使用すると、この元のタイプのデータ変数は本当に1回付与されます.しかし、参照タイプの変数に対しては、付与されます.付与された変数がこの参照タイプを指すだけです.下の栗が見えます.
この栗の中で、私たちがどのようにその値を変えてもcountは変化しないことに気づきます.これは私たちが上述したように、これを説明する前に、$watchの3番目のパラメータを説明し、一般的に$watch関数の最初の2つのパラメータは必ず伝達され(監視対象、コールバック関数)、3番目のパラメータはfalseとデフォルトで、このように私たちが行う監視制御は参照監視と呼ばれています.この意味は、モニタリングオブジェクトのアプリケーションが変化していない場合はオブジェクトが変化しているとはみなされません.具体的には、上記の例では、itemsの属性が変化しても、itemsの参照が変化していない限り、$watchは見えないと見なされますが、例えば、1つの配列がitemsに付与されている場合、この時$watchは見えなくなりました(太陽の光をあげると輝いて返します).逆に、3番目のパラメータがtrueに設定されている場合、私たちのモニタリングは「全等モニタリング」と呼ばれています.このときの$watchの要求は厳しいです.彼がモニタリングしているオブジェクトが少し変化している限り、$watchは飛び出して、寝溝になります.君は意外にも動く勇気がある!!!
もちろん、3番目のパラメータにtrueを追加するのはなぜですか.こんなに便利になったのに、私たちはまだ追加しませんか.もちろん性能にかかわる問題です!全等監視が動作するときは、まずオブジェクト全体を監視し、毎回バー$digesが走る前にangualr.を使用します.copy()オブジェクト全体をコピーしてからangularを呼び出す.equal()メソッドを比較するため、このモニタリングは大量のリソースを消費する可能性があります.
angularJS 1.1.4では、配列の集合を監視するための$watchCollection()メソッドが追加されました.彼の性能は、参照監視と全等監視の間にあり、配列の各内容を監視するのではなく、配列のpopとpushに反応します.具体的な栗は余計なことは言わない.
次に$applyについてお話しします.彼の役割は同期の変更をインタフェースにバインドすることですが、なぜ存在するのでしょうか.いつ使う必要がありますか?いつまたいらないの?では、まずangularがどのようにデータの双方向バインドを行っているのかについてお話ししましょう.1つの変数が変わったことを知っておくには、方法は2つの1にほかならない.セット、getなどの固定インタフェースを通じて、setで変数の値を設定し、setが呼び出されたときに比較すればいいが、この方法は複雑だ.2、汚れチェック、あるオブジェクトをスナップショットをコピーし、ある時間に、現在のオブジェクトとスナップショットの値を比較します.明らかに、この方法では2つのオブジェクトをコピーし、オブジェクトを巡回して各プロパティを比較します.そうだ!これは確かに性能の問題があります!しかしangularはこれを使います~しかし人angularの汚い検査はすべてのオブジェクトに対して検査を行うのではありませんて、ただオブジェクトがhtmlの中にバインドする時、このオブジェクトはやっと検査オブジェクト(watcher)を複合して、同様に、angularは属性の汚い検査に対してもこのようです.watcherオブジェクトのソースコードを見てみましょう.
では、私たちはいつ汚れ検査をしますか?汚れたチェックのポイントは関数の実行が完了した後ですが、非同期呼び出しを明記しなくても実行が完了し、私たちの機能が非同期であれば、私たちの変更はDOMに更新されていないことがわかります.栗を挙げます.
簡単に言えばdomにはTimeout calledは永遠に表示されません.もちろん、これは私たちの$applyのアプリケーションシーンです.それを呼び出し、手動で汚れ検査をトリガーします.例えば、angularJsは$timeoutを提供しています.なぜsettimoutがあればこれを提供しますか.$timeoutの非同期完了後、angularJsは$applyを自動的にトリガーします.
次に$applyの使用上の注意点を説明しましょう.$applyを持つ環境でapplyを使用すると、異常が放出されます.だから、私たちのコードが$apply環境ではなく、構造が非同期で返されているとしたら、$applyApplyがパラメータとして受け入れる関数を手動でトリガーする必要があります.関数にバインドされているオブジェクトは汚れて検査され、functionは非同期ではありません.もちろん、apply関数のパラメータが空の場合、現在の役割ドメイン内のすべての汚れたオブジェクトがチェックされます.パフォーマンスの無駄!
しかし、この汚い検査はどうやって検査したのでしょうか.では、$digest関数について説明します.$applyが呼び出されると、最終的に$digest()が$scope.$を呼び出されます.digest()の後、$digestサイクルが始まります.ng-click命令に対応するhandler関数でscopeのデータを変更すると、AngularJSは$digest()を呼び出して$digestループを自動的にトリガーします.$digestサイクルが開始されると、各watcherがトリガーされます.これらのwatchersはscopeの現在のmodel値が前回計算したmodel値と異なるかどうかをチェックします.異なる場合、対応するコールバック関数が実行されます.この関数を呼び出すと、viewの式の内容が更新されます.ng-clickコマンドに加えて、ng-model、$timeoutなどのmodelsを変更し、$digestループを自動的にトリガーする他のbuilt-inコマンドやサービスもあります.
ひとまずこれだけにしておきましょう.たくさん言ってもぼんやりしていて、自分で実際に応用して体得しなければならないことが多いです.
$watch$watchは、モデルの変化を簡単に監視し、栗を挙げることができます.
<html>
<head>
<script src='./lib.angular.min.js'></script>
</head>
<body ng-app='watch'>
<input ng-model='name' type='text'/>
<div>change count: {{count}}</div>
<script>
angular.module('watch',[])
.run(['$rootScope',function($rootScope){
$rootScope.count = 0;
$rootScope.name = 'Alfred';
$rootScope.$watch('name',function(){
$rootScope.count++;
})
}]);
</script>
</body>
</html>
上のコードはnameの変化を監視するために使用され、input入力ボックスに値を入力するたびに$rootScopeのcountが+1に対応します.
angularJSの内部では、nameの値を変更するたびにangularJSの内部の$digestが呼び出され(以下、$digestの原理を詳細に説明する)、実行終了後に$watchで監視したモデルをチェックし、前回の$digestの実行前と比較してどのように変化したかを確認すると、$watchのコールバック関数が実行されます.
しかし!!我々の実際の開発では、1つの元のタイプのデータモニタリングを実現するだけでは、必要なものをはるかに満たすことができません.元のタイプのデータに対して、1回の付与操作を使用すると、この元のタイプのデータ変数は本当に1回付与されます.しかし、参照タイプの変数に対しては、付与されます.付与された変数がこの参照タイプを指すだけです.下の栗が見えます.
<html>
<head>
<script src='./lib.angular.min.js'></script>
</head>
<body ng-app='watch'>
<div ng-repeat='item in items'>
<input ng-model='item.a'/><span>{{item.a}}</span>
</div>
<div>change count: {{count}}</div>
<script>
angular.module('watch',[])
.run(['$rootScope',function($rootScope){
$rootScope.count = 0;
$rootScope.items = [
{ "a": 1 },
{ "a": 2 },
{ "a": 3 },
{ "a": 4 }
]
$rootScope.$watch('items',function(){
$rootScope.count++;
})
}]);
</script>
</body>
</html>
この栗の中で、私たちがどのようにその値を変えてもcountは変化しないことに気づきます.これは私たちが上述したように、これを説明する前に、$watchの3番目のパラメータを説明し、一般的に$watch関数の最初の2つのパラメータは必ず伝達され(監視対象、コールバック関数)、3番目のパラメータはfalseとデフォルトで、このように私たちが行う監視制御は参照監視と呼ばれています.この意味は、モニタリングオブジェクトのアプリケーションが変化していない場合はオブジェクトが変化しているとはみなされません.具体的には、上記の例では、itemsの属性が変化しても、itemsの参照が変化していない限り、$watchは見えないと見なされますが、例えば、1つの配列がitemsに付与されている場合、この時$watchは見えなくなりました(太陽の光をあげると輝いて返します).逆に、3番目のパラメータがtrueに設定されている場合、私たちのモニタリングは「全等モニタリング」と呼ばれています.このときの$watchの要求は厳しいです.彼がモニタリングしているオブジェクトが少し変化している限り、$watchは飛び出して、寝溝になります.君は意外にも動く勇気がある!!!
もちろん、3番目のパラメータにtrueを追加するのはなぜですか.こんなに便利になったのに、私たちはまだ追加しませんか.もちろん性能にかかわる問題です!全等監視が動作するときは、まずオブジェクト全体を監視し、毎回バー$digesが走る前にangualr.を使用します.copy()オブジェクト全体をコピーしてからangularを呼び出す.equal()メソッドを比較するため、このモニタリングは大量のリソースを消費する可能性があります.
angularJS 1.1.4では、配列の集合を監視するための$watchCollection()メソッドが追加されました.彼の性能は、参照監視と全等監視の間にあり、配列の各内容を監視するのではなく、配列のpopとpushに反応します.具体的な栗は余計なことは言わない.
次に$applyについてお話しします.彼の役割は同期の変更をインタフェースにバインドすることですが、なぜ存在するのでしょうか.いつ使う必要がありますか?いつまたいらないの?では、まずangularがどのようにデータの双方向バインドを行っているのかについてお話ししましょう.1つの変数が変わったことを知っておくには、方法は2つの1にほかならない.セット、getなどの固定インタフェースを通じて、setで変数の値を設定し、setが呼び出されたときに比較すればいいが、この方法は複雑だ.2、汚れチェック、あるオブジェクトをスナップショットをコピーし、ある時間に、現在のオブジェクトとスナップショットの値を比較します.明らかに、この方法では2つのオブジェクトをコピーし、オブジェクトを巡回して各プロパティを比較します.そうだ!これは確かに性能の問題があります!しかしangularはこれを使います~しかし人angularの汚い検査はすべてのオブジェクトに対して検査を行うのではありませんて、ただオブジェクトがhtmlの中にバインドする時、このオブジェクトはやっと検査オブジェクト(watcher)を複合して、同様に、angularは属性の汚い検査に対してもこのようです.watcherオブジェクトのソースコードを見てみましょう.
watcher = {
fn: listener, //
last: initWatchVal, //
get: get, //
exp: watchExp, //
eq: !!objectEquality //
};
では、私たちはいつ汚れ検査をしますか?汚れたチェックのポイントは関数の実行が完了した後ですが、非同期呼び出しを明記しなくても実行が完了し、私たちの機能が非同期であれば、私たちの変更はDOMに更新されていないことがわかります.栗を挙げます.
<!-- lang: js -->
function Ctrl($scope) {
$scope.message = "Waiting 2000ms for update";
setTimeout(function () {
$scope.message = "Timeout called!"; // AngularJS unaware of update to $scope }, 2000); }
簡単に言えばdomにはTimeout calledは永遠に表示されません.もちろん、これは私たちの$applyのアプリケーションシーンです.それを呼び出し、手動で汚れ検査をトリガーします.例えば、angularJsは$timeoutを提供しています.なぜsettimoutがあればこれを提供しますか.$timeoutの非同期完了後、angularJsは$applyを自動的にトリガーします.
次に$applyの使用上の注意点を説明しましょう.$applyを持つ環境でapplyを使用すると、異常が放出されます.だから、私たちのコードが$apply環境ではなく、構造が非同期で返されているとしたら、$applyApplyがパラメータとして受け入れる関数を手動でトリガーする必要があります.関数にバインドされているオブジェクトは汚れて検査され、functionは非同期ではありません.もちろん、apply関数のパラメータが空の場合、現在の役割ドメイン内のすべての汚れたオブジェクトがチェックされます.パフォーマンスの無駄!
しかし、この汚い検査はどうやって検査したのでしょうか.では、$digest関数について説明します.$applyが呼び出されると、最終的に$digest()が$scope.$を呼び出されます.digest()の後、$digestサイクルが始まります.ng-click命令に対応するhandler関数でscopeのデータを変更すると、AngularJSは$digest()を呼び出して$digestループを自動的にトリガーします.$digestサイクルが開始されると、各watcherがトリガーされます.これらのwatchersはscopeの現在のmodel値が前回計算したmodel値と異なるかどうかをチェックします.異なる場合、対応するコールバック関数が実行されます.この関数を呼び出すと、viewの式の内容が更新されます.ng-clickコマンドに加えて、ng-model、$timeoutなどのmodelsを変更し、$digestループを自動的にトリガーする他のbuilt-inコマンドやサービスもあります.
ひとまずこれだけにしておきましょう.たくさん言ってもぼんやりしていて、自分で実際に応用して体得しなければならないことが多いです.