【问题标题】:Angular js - Highlight dom when value changesAngular js - 值更改时突出显示dom
【发布时间】:2013-12-05 14:56:10
【问题描述】:

Angular 新手在这里。 我想知道当范围内的值以某种方式发生变化时,更改 dom 的最佳方法是什么。我读到将 dom 操作逻辑放在控制器中并不好,这就是指令的工作。

这是一个小插曲

http://plnkr.co/edit/xWk5UBwifbCF2raVvw81?p=preview

基本上,当通过单击上面 plunkr 中的加载数据按钮更改数据时,我希望其值更改的单元格自动突出显示。我无法让它为我的一生工作。

有什么帮助吗?

【问题讨论】:

    标签: javascript angularjs angularjs-directive


    【解决方案1】:

    我认为最好观察每个 highlighter 的具体值,而不是观察整个集合。例如:

    <td highlighter="person.firstName">{{ person.firstName }}</td>
    

    这样,highlighter-directive 可以非常简单,例如:

    app.directive('highlighter', ['$timeout', function($timeout) {
      return {
        restrict: 'A',
        scope: {
          model: '=highlighter'
        },
        link: function(scope, element) {
          scope.$watch('model', function (nv, ov) {
            if (nv !== ov) {
              // apply class
              element.addClass('highlight');
    
              // auto remove after some delay
              $timeout(function () {
                element.removeClass('highlight');
              }, 1000);
            }
          });
        }
      };
    }]);
    

    不过,要使其正常工作,您必须告诉 Angular 数据实际发生了变化。目前情况并非如此,因为对象身份的角度轨道people。覆盖它的那一刻,angular 将删除所有关联的 dom 元素。为此,请使用:

    ng-repeat="person in people track by $index"
    

    这将告诉 Angular 将数组的索引视为身份。

    演示:http://jsbin.com/vutevifadi/1/

    【讨论】:

    • 我知道track by $index 可以修复对象中的重复值,但很高兴知道它也修复了newVal, oldVal 问题。我很困惑为什么他们在这种情况下总是平等的。
    • 当心!范围不是孤立的。这将在 $rootScope 上触发 $digest!
    【解决方案2】:

    感谢您在上面发布答案。我注意到如果值频繁更改,动画会闪烁,并且在另一个动画已经处于活动状态时会触发超时。

    如果已设置超时,我已通过重置超时来解决此问题。

    另外,我添加了代码来检查值是增加还是减少并设置不同的 css 类。

    app.directive('newvalue', ['$timeout', function($timeout) {
      return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.addClass('newvalue');
            scope.$watch(attrs.newvalue, function (nv, ov) {
            function settimeout() {
                attrs.timeout = $timeout(function () {
                    element.removeClass('newvalue-up');
                    element.removeClass('newvalue-down');
                    attrs.timeout = null;
                }, 1000);
            }
            if (nv !== ov) {
                if(attrs.timeout) {
                    //newvalue already set.. reset timeout
                    $timeout.cancel(attrs.timeout);
                    settimeout();
                } else {
                    if(nv > ov) {
                        element.addClass('newvalue-up');
                    } else {
                        element.addClass('newvalue-down');
                    }
                    settimeout();
                }
            }
          });
        }
      };
    }]);
    

    【讨论】:

    • 当心!范围不是孤立的。这将在 $rootScope 上触发 $digest!
    • 这种情况下的属性是什么?是怎么传入的?
    • @Shuliyey 是来自 dom 元素的属性。
      之类的..
    • @Jonathan 一个解决方案会很棒吗?这里做错了什么?
    【解决方案3】:

    经过阅读后,我注意到考虑到性能,使用$watch 存在一些疑问。我使用$observe找到了另一个解决方案。

    好好阅读$watch$observehttps://stackoverflow.com/a/14907826/2901207

    javascript:

    var app = angular.module('angularjs-starter', []);
    app.directive('highlightOnChange', function() {
      return {
        link : function(scope, element, attrs) {
          attrs.$observe( 'highlightOnChange', function ( val ) {
            console.log("Highlighting", val);
            element.effect('highlight');
          });
        }
      };
    });
    
    app.controller('myController', function($scope, $timeout) {
      $scope.val = 1;
      $scope.updateVal = function() {
        $scope.val = $scope.val + 1;
      };
    }); 
    

    html:

      <body ng-controller="myController">
        <div highlight-on-change="{{val}}">
          Total: {{ val }}
        </div>
        <button ng-click="updateVal()">Add to Total</button>
      </body>
    

    原文来源:http://plnkr.co/edit/FFBhPIRuT0NA2DZhtoAD?p=preview 来自这篇文章:https://groups.google.com/d/msg/angular/xZptsb-NYc4/YH35m39Eo2wJ

    有点复杂的用法,这对我来说非常适合,因为它会在更新即将到来时突出显示特定列。

    <table class="table table-hover">
            <tr>
                <th ng-repeat="col in fc.tableColumns"><!--fc is a controller-->
                    {{col.displayName}}
                </th>
            </tr>
            <tr ng-repeat="item in fc.items track by item.id">
                <td highlight-on-change="{{value}}" ng-repeat="(key,value) in item">
                   @*{{key}} =*@ {{value}}
                </td>
            </tr>
        </table>
    

    正如我所说,更新特定列,同时在控制器中的某处执行此操作。

    items[index] = item;//item from server
    

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签