AngularJS:$ watch vs. $ observe newValue === oldValue

时间:2015-05-20 17:44:10

标签: javascript angularjs angularjs-directive

如果已经在某处解释或讨论过这个问题,我很抱歉,但我无法在任何地方找到这个确切的问题。

所以我有一个带有一个数据绑定的角度指令' myvar' (=或@没有区别)。数据绑定的值在指令中使用:scope.myvarStr = scope.myvar +' somestring'。然后我将myvarStr绑定在模板中。

因为scope.myvar更改时必须修改scope.myvarStr,所以我使用$ watch(' myvar',function(...))来监视值并在需要时更新scope.myVarStr。在watch函数中我把经典if(newValue === oldValue)返回;

问题开始于$ watch手表被解雇且两个值相等;然后视图没有更新。我可以很容易地从链接函数的第一行的console.log(scope.myvar)中看到scope.myvar未定义(或者依赖于绑定类型)以及该值开始当我在$ watch中执行console.log时,已经改变了别的东西。

我用Google搜索了一个小时左右,发现了这个:https://github.com/angular/angular.js/issues/11565 但是,这个问题在其他任何地方都没有讨论过,所以我用Google搜索了更多内容并遇到了$ observe AngularJS : Difference between the $observe and $watch methods

当我从$ watch更改为$ observe时,我的所有问题都消失了,我仍然可以使用if(newValue === oldValue)return;。

(function(directives) {
'use strict';

directives.directive('someDir', [function() {
    return {
        restrict: 'E',
        scope: {
            myvar: '=' //or @ didn't matter at the time...
        },
        template: '<p>{{myvarStr}}</p>',
        link: function(scope, el, attrs) {

            function toString() {
                if (scope.myvar < 1000) {
                    scope.myvarStr = scope.myvar;
                } else {
                    scope.myvarStr = scope.myvar/1000 + 'k';
                }
            }
            toString();

            scope.$watch('myvar', function(newValue, oldValue) {
                console.log("changed", newValue, oldValue)
                if (newValue == oldValue) return;
                toString();
            },true);

            // When changing to $observe it works :)
            //attrs.$observe('myvar', function(newValue, oldValue) {
            //    console.log("changed", newValue, oldValue)
            //    if (newValue == oldValue) return;
            //    toString();
            //},true);

        }
    };
}]);
}(angular.module('myApp.directives')));

建议:据我所知,$ watch会出现此问题,因为范围值永远不会更改。指令需要一段时间来获取值,直到那时绑定只是一个空字符串或其他东西,当检测到值时,$ watch触发但实际范围值没有改变(或者如第一个链接中所解释的那样) ;当指令中出现值&#39;时,第一只手表会闪光。

1 个答案:

答案 0 :(得分:0)

我不太明白你的建议/解释,但我觉得事情要比看上去简单得多。

您不需要where REGEXP_SIMILAR (int_cust_ip_addr, '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$') = 1 测试,因为您的观察行为是幂等且便宜的。但即使你这样做,也只是意味着你需要自己初始化值(例如通过手动调用newValue === oldValue),你似乎正在做,因此你的指令应该按预期工作。 (事实上​​,我无法重现您在代码中提到的问题。)

无论如何,这是一个(更简单)working version

toString()
顺便说一句,因为你只是试图“格式化”一些显示值,所以似乎过滤器.directive('test', function testDirective() { return { restrict: 'E', template: '<p>{{ strVal }}</p>', scope: { val: '=' }, link: function testPostLink(scope) { scope.$watch('val', function prettify(newVal) { scope.strVal = (!newVal || (newVal < 1000)) ? newVal : (newVal / 1000) + 'K'; }); } }; }) 更合适(并且清晰imo)(参见above demo):

$watch