在链接中使用手表会导致无限的摘要周期。

时间:2014-04-22 00:32:27

标签: javascript angularjs angularjs-directive

我正在尝试编写一个将分数与颜色相关联的指令。

我已经尝试了,而且Plunker是here。指令本身就在这里:

.directive('scorebox', function () {
    function link ($scope, $elem, $attr) {
        var one = 1;
        $scope.$watch('[score,ptsPossible]', function (newValue) {
            pctScore = newValue[0] / newValue[1]
            if (pctScore <= 0.4) {
                rating = 'low';
            } else if (pctScore <= 0.6) {
                rating = 'med';
            } else if (pctScore <= 0.8) {
                rating = 'high';
            } else if (pctScore == 1) {
                rating = 'perfect';
            }

            $elem.removeClass();
            $elem.addClass('scorebox');
            $elem.addClass(rating);
            $elem.text(newValue[0] + "/" + newValue[1]);
        });
    };

    return {
        restrict: 'E',
        scope: {
            score: "=",
            ptsPossible: "="
        },
        link:link 
    }
}) 

我有几个问题。

  1. 首先,对我来说很明显,我应该在$watch函数中执行link。我正在创造一个无限的消化周期,这并不好。不过,我仍然不确定原因。
  2. 我没有正确操作DOM。即使我正在调用$elem.removeClass(),它也不起作用 - 该元素保留了以前的任何类。
  3. 这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

只是建议让事情顺利进行:

  1. $watchscore都不需要ptsPossible,因为后者在从相应的属性值加载值后永远不会更改。您还可以访问scope回调函数中的$watch个变量。
  2. 这很不寻常,因为我希望你的removeClass()能够正常工作。你可以在此同时尝试removeAttr('class')
  3. 这里有一个Plunker,其中包含建议的更改。

答案 1 :(得分:1)

您需要使用$watchCollection而不是$watch。您将数组传递给$watch,这是$watchCollection期望的结果。

答案 2 :(得分:1)

  1. 正如@miqid所说,没有必要同时观察得分和ptsPossible,因为你只想在得分发生变化时作出反应(至少在这种情况下你会提出)。

  2. 这里的问题是,你使用 jqLit​​e的 removeClass函数而不是 jQuery的。如果在代码中Angular之前没有包含jQuery,Angular将使用jqLit​​e函数,这就像一个更小,更简单的jQuery版本。它也略有不同。 jQuery的 removeClass(),将删除所有类都没有参数传递。 jqLit​​e不会这样做,它只会删除你作为参数传递的那些类。

  3. 你根本就没有包含jQuery,所以这就是正在发生的事情。这是经过编辑的Plunker。您可以检查jQuery现在包含在顶部,一切都按预期工作。 $ watch也更简单。