Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript $同时观察多个属性并仅触发一次回调_Javascript_Angularjs - Fatal编程技术网

Javascript $同时观察多个属性并仅触发一次回调

Javascript $同时观察多个属性并仅触发一次回调,javascript,angularjs,Javascript,Angularjs,我想知道在对指令的所有(或仅某些)属性求值之后(没有隔离的作用域),是否可以只执行一次回调。属性非常适合将配置传递给指令。问题是,您可以单独观察每个属性并多次触发回调 在这个例子中,我们有一个没有独立作用域的指令,它观察两个属性:name和names。在触发任何更改操作回调后: html <button ng-click="name='John';surname='Brown'">Change all params</button> <div person name

我想知道在对指令的所有(或仅某些)属性求值之后(没有隔离的作用域),是否可以只执行一次回调。属性非常适合将配置传递给指令。问题是,您可以单独观察每个属性并多次触发回调

在这个例子中,我们有一个没有独立作用域的指令,它观察两个属性:name和names。在触发任何更改
操作
回调后:

html

<button ng-click="name='John';surname='Brown'">Change all params</button>
<div person name="{{name}}" surname="{{surname}}"></div>

所以问题是:
action
是否只能在名称和姓氏值都更改的情况下触发一次?

您可以使用
$watch
评估自定义函数,而不是特定模型

i、 e

这将在所有
$digest
周期上运行,如果
$watch
检测到返回数组(或以您希望的方式构造函数的返回值)与旧值不匹配,则将触发
$watch
的回调参数。如果确实使用对象作为返回值,请确保将最后一个参数的
true
值保留在
$watch
中,以便
$watch
将进行深入比较。

下划线(或短划线)有一个
once
函数。如果将函数包装在
中一次
,则可以确保函数只被调用一次

angular.module('app',[])。
指令('person',函数(){
返回{
限制:“A”,
链接:函数($scope、$elem、$attrs){
var action=function(){
$elem.append('name:'+$attrs.name+'
姓氏:'+$attrs.姓氏+'

); } var once=u0.once(操作); $attrs.$observe('name',一次); $attrs.$observe(‘姓’,一次); } } });
因此,我最终实现了自己的
observeAll
方法,它可以在一个调用堆栈中等待属性的多次更改。它的工作,但我不确定的性能

@cmw的解决方案似乎更简单,但当多次评估对象相等性时,大量参数和多个$digest阶段运行可能会影响性能。然而,我决定接受他的回答

您可以在下面找到我的方法:

angular.module('utils.observeAll', []).

factory('observeAll', ['$rootScope', function($rootScope) {
    return function($attrs, callback) {
        var o = {}, 
            callQueued = false, 
            args = arguments,

            observe = function(attr) {
                $attrs.$observe(attr, function(value) {
                    o[attr] = value;
                    if (!callQueued) {
                        callQueued = true;
                        $rootScope.$evalAsync(function() {
                            var argArr = [];
                            for(var i = 2, max = args.length; i < max; i++) {
                                var attr = args[i];
                                argArr.push(o[attr]);
                            }
                            callback.apply(null, argArr);
                            callQueued = false;
                        });
                    }
                });
            };

        for(var i = 2, max = args.length; i < max; i++) {
            var attr = args[i];
            if ($attrs.$attr[attr])
                observe(attr);
        }
    };
}]);
angular.module('utils.observeAll',[])。
工厂('observeAll',['$rootScope',函数($rootScope){
返回函数($attrs,callback){
var o={},
callQueued=false,
args=参数,
观察=功能(attr){
$attrs.$observe(attr,函数(值){
o[attr]=值;
如果(!callQueued){
callQueued=true;
$rootScope.$evalAsync(函数(){
var argArr=[];
对于(变量i=2,max=args.length;i
您可以在指令中使用它:

angular.module('app', ['utils.observeAll']).

directive('person', ['observeAll', function(observeAll) {
  return {
    restrict: 'A',
    link: function($scope, $elem, $attrs) {
        var action = function() {
          $elem.append('name: ' + $attrs.name + '<br/> surname: ' + $attrs.surname+'<br/><br/>');
        }
        observeAll($attrs, action, 'name', 'surname');
    }
 }
}]);
angular.module('app',['utils.observeAll'])。
指令('person',['observeAll',函数(observeAll){
返回{
限制:“A”,
链接:函数($scope、$elem、$attrs){
var action=function(){
$elem.append('name:'+$attrs.name+'
姓氏:'+$attrs.姓氏+'

); } observeAll($attrs,action,'name','姓氏'); } } }]);

Plunker

我用另一种方法解决了完全相同的问题,尽管我在寻找不同的想法。当cmw的建议起作用时,我将它的性能与我的进行了比较,发现$watch方法被调用的次数太多了,所以我决定保持我实现的方式

我为我想要跟踪的两个变量添加了$observe调用,并将它们绑定到去盎司调用。由于两个$observe方法都是在时间差很小的情况下修改的,因此两个$observe方法都会触发相同的函数调用,并在短时间延迟后执行:

var debounceUpdate = _.debounce(function () {
    setMinAndMaxValue(attrs['minFieldName'], attrs['maxFieldName']);
}, 100);

attrs.$observe('minFieldName', function () {
    debounceUpdate();
});

attrs.$observe('maxFieldName', function () {
    debounceUpdate();
});

有几种方法可以解决这个问题。我非常喜欢去盎司溶液。然而,这是我对这个问题的解决方案。这将所有属性合并到一个属性中,并创建您感兴趣的属性的JSON表示。现在,你只需要观察一个属性,并有良好的性能了

以下是原始plunkr的分支及其实现:
链接

不幸的是,
一旦
将只触发一次回调,但仅在第一个属性更改后才会触发。我的观点是,在单个
$digest
阶段的所有更改之后,应该触发回调。
angular.module('utils.observeAll', []).

factory('observeAll', ['$rootScope', function($rootScope) {
    return function($attrs, callback) {
        var o = {}, 
            callQueued = false, 
            args = arguments,

            observe = function(attr) {
                $attrs.$observe(attr, function(value) {
                    o[attr] = value;
                    if (!callQueued) {
                        callQueued = true;
                        $rootScope.$evalAsync(function() {
                            var argArr = [];
                            for(var i = 2, max = args.length; i < max; i++) {
                                var attr = args[i];
                                argArr.push(o[attr]);
                            }
                            callback.apply(null, argArr);
                            callQueued = false;
                        });
                    }
                });
            };

        for(var i = 2, max = args.length; i < max; i++) {
            var attr = args[i];
            if ($attrs.$attr[attr])
                observe(attr);
        }
    };
}]);
angular.module('app', ['utils.observeAll']).

directive('person', ['observeAll', function(observeAll) {
  return {
    restrict: 'A',
    link: function($scope, $elem, $attrs) {
        var action = function() {
          $elem.append('name: ' + $attrs.name + '<br/> surname: ' + $attrs.surname+'<br/><br/>');
        }
        observeAll($attrs, action, 'name', 'surname');
    }
 }
}]);
var debounceUpdate = _.debounce(function () {
    setMinAndMaxValue(attrs['minFieldName'], attrs['maxFieldName']);
}, 100);

attrs.$observe('minFieldName', function () {
    debounceUpdate();
});

attrs.$observe('maxFieldName', function () {
    debounceUpdate();
});