gpt4 book ai didi

javascript - angularJS中这些监视方法之间的区别?

转载 作者:可可西里 更新时间:2023-11-01 02:03:02 24 4
gpt4 key购买 nike

我在使用 watch 时遇到问题,我想观察一个数组对象,让我们假设如果对象中的任何数组发生变化,那么 watch 应该被解雇,所以我对为此目的使用什么感到困惑。

任何人都可以帮我找出这两者之间的区别并建议在这种情况下使用什么。

作用域对象:

$scope.$watch('foo', fn)
$scope.$watch(function() {return $scope.foo}, fn);

$scope.$watchCollection('foo', fn)
$scope.$watchCollection(function() {return $scope.foo}, fn);

非范围对象:

$scope.$watch(obj.prop, fn)
$scope.$watch(function() {return obj.prop}, fn)

$scope.$watchCollection(obj.prop, fn)
$scope.$watchCollection(function() {return obj.prop}, fn)

最佳答案

请参阅 https://docs.angularjs.org/guide/scope 上的“Scope $watch Depths” .其中有一个特别有用的图形:

enter image description here

针对作为“具有数组属性的对象”的 $scope 属性(如果我理解正确的话),我演示了一些不同的 $watcher 下面代码段中的配置,以便您可以看到实际的各种行为。

(function() {
"use strict";

angular.module('myApp', [])
.controller("Controller1", ['$scope', Controller1]);

function Controller1($scope) {
var _objWithArrayProps = {
'prop1': [],
'prop2': [],
'prop3': []
},
_counts = {
'watchNoObjEquality': -1, //watchers to -1 since they fire once upon initialisation
'watchPropNoObjEquality': -1,
'watchObjEquality': -1,
'watchFunctionNoObjEquality': -1,
'watchFunctionObjEquality': -1,
'watchCollection': -1,
'watchCollectionFunction': -1,
'clicks': 0
};

$scope.data = {
'objWithArrayProps': _objWithArrayProps,
'counts': _counts
};

$scope.$watch('data.objWithArrayProps', watchNoObjEquality);
$scope.$watch('data.objWithArrayProps.prop1', watchPropNoObjEquality);
$scope.$watch('data.objWithArrayProps', watchObjEquality, true);
$scope.$watch(watchFunction, watchFunctionNoObjEquality);
$scope.$watch(watchFunction, watchFunctionObjEquality, true);
$scope.$watchCollection('data.objWithArrayProps', watchCollection);
$scope.$watchCollection(watchFunction, watchCollectionFunction);

$scope.addProperty = addProperty;
$scope.addArrayElements = addArrayElements;
$scope.modifyProperties = modifyProperties;
$scope.modifyArrayElements = modifyArrayElements;

function watchNoObjEquality(newVal, oldVal) {
_counts.watchNoObjEquality++;
}

function watchPropNoObjEquality(newVal, oldVal) {
_counts.watchPropNoObjEquality++;
}

function watchObjEquality(newVal, oldVal) {
_counts.watchObjEquality++;
}

function watchFunction() {
return _objWithArrayProps; // same as: return $scope.data.objWithArrayProps;
}

function watchFunctionNoObjEquality(newVal, oldVal) {
_counts.watchFunctionNoObjEquality++;
}

function watchFunctionObjEquality(newVal, oldVal) {
_counts.watchFunctionObjEquality++;
}

function watchCollection(newVal, oldVal) {
_counts.watchCollection++;
}

function watchCollectionFunction(newVal, oldVal) {
_counts.watchCollectionFunction++;
}

var _propNameNumberSuffix = 4; //for naming properties incrementally
function addProperty() {
_counts.clicks++;
_objWithArrayProps['prop' + _propNameNumberSuffix] = [];
_propNameNumberSuffix++;
}

function addArrayElements() {
_counts.clicks++;
for (var prop in _objWithArrayProps) {
if (_objWithArrayProps.hasOwnProperty(prop)) {
_objWithArrayProps[prop].push('x');
}
}
}

function modifyProperties() {
_counts.clicks++;
for (var prop in _objWithArrayProps) {
if (_objWithArrayProps.hasOwnProperty(prop)) {
_objWithArrayProps[prop] = [Math.random()]; //set to a fresh array with a random number in it
}
}
}

function modifyArrayElements() {
_counts.clicks++;
for (var prop in _objWithArrayProps) {
if (_objWithArrayProps.hasOwnProperty(prop)) {
//ensure we have at least one item in array(s)
if (!_objWithArrayProps[prop].length) {
_objWithArrayProps[prop].push('x');
}

for (var i = 0, iLen = _objWithArrayProps[prop].length; i < iLen; i++) {
_objWithArrayProps[prop][i] = Math.random().toFixed(4);
}
}
}
}

}

})();
body {
font-family: "Arial", "sans-serif";
font-size: 0.8em;
}
h1 {
font-size: 1.4em;
}
pre {
margin: 0;
}
pre code {
display: block;
background-color: #eee;
padding: 5px;
max-height: 200px;
overflow: auto;
}
ul.tab li span {
display: inline-block;
margin: 5px 0;
}
ul.tab li {
border-bottom: 1px dashed #ddd;
display: block;
padding: 0;
}
ul.tab {
padding: 0;
}
#data,
#counts {
width: 45%;
display: inline-block;
vertical-align: top;
margin: 2%;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<div ng-app="myApp" ng-controller="Controller1">
<h1>Object with Array properties</h1>
<div id='counts'>
<strong>Watcher fired count:</strong>
<ul class="tab">
<li><span><strong>$watch</strong>('objWithArrayProps', ...) :</span> {{data.counts.watchNoObjEquality}}</li>
<li><span><strong>$watch</strong>('objWithArrayProps.prop1', ...) :</span> {{data.counts.watchPropNoObjEquality}}</li>
<li><span><strong>$watch</strong>('objWithArrayProps', ..., true) :</span> {{data.counts.watchObjEquality}}</li>
<li><span><strong>$watch</strong>(function() {...}, ...) :</span> {{data.counts.watchFunctionNoObjEquality}}</li>
<li><span><strong>$watch</strong>(function() {...}, ..., true) :</span> {{data.counts.watchFunctionObjEquality}}</li>
<li><span><strong>$watchCollection</strong>('objWithArrayProps', ...) :</span> {{data.counts.watchCollection}}</li>
<li><span><strong>$watchCollection</strong>(function() {...}, ...) :</span> {{data.counts.watchCollectionFunction}}</li>
</ul>
<strong>Button clicks:</strong> {{data.counts.clicks}}
</div>
<div id='data'>
<pre><code>{{data.objWithArrayProps | json}}</code></pre>
</div>
<button ng-click="addProperty()">Add a property</button>
<button ng-click="addArrayElements()">Add array elements</button>
<button ng-click="modifyProperties()">Modify properties</button>
<button ng-click="modifyArrayElements()">Modify array elements</button>
</div>

( Plnkr <-- 为了更容易实验)

$watch(..., ..., true)

如您在代码片段中所见,如果您想要保证捕捉到嵌套 对象/数组结构的每一个微小变化,请使用$scope。 $watch(..., ..., true),其中第三个参数导致观察器对对象/数组中的每个属性进行深入比较。但是,这样做相对繁重,因此请注意,大型对象可能会对性能产生一些影响。

$watch(function(){}, ..., ...)

$scope.$watch(function() {...}, ...) 格式实际上为您提供了比我在代码片段中演示的更多的灵 active ,但是,我基本上只是返回对象。您的函数的返回值将与其之前的返回值进行比较(每次 $digest 运行时),因此如果您希望监听器函数触发,您需要在正确的位置返回不同的值次。理想情况下,出于性能原因,您希望此功能非常轻便和简单(它会被执行很多次!),但根据您需要观察的数据,您可能能够实现性能更好的解决方案比 $scope.$watch(..., ..., true)

$watchCollection(..., ...)

正如您在代码片段中看到的,这仅响应集合的浅层更改(无论是对象还是数组)——它会注意到是否添加、删除、移动了属性,以及它是否包含基本值,例如一个字符串、数字、 bool 值等,如果它发生变化,它会注意到。但是,如果您的集合包含更多嵌套的对象/数组,它将不会注意到它们内部的变化(它们太深了)。因此需要上述两个 $watch 实现中的任何一个。

ng 事件

如果您感兴趣的模型更改仅由用户输入引起,还请记住考虑是否可以使用 ng-changeng-blur (等)表单控件上的事件而不是模型上的观察者,因为这些很可能会表现得更好。

关于javascript - angularJS中这些监视方法之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31183353/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com