Angular ng-class применяется по-разному в 1.3.0 по сравнению с 1.2.25.

У меня есть относительно большое приложение Angular, построенное поверх версии 1.2.25. В моем недавнем обновлении до 1.3.0 я обнаружил только одну серьезную проблему, которая, кажется, меняется, когда изменения класса html вносятся в DOM.

В этом примере jsfiddle обратите внимание на часы, которые получают размер элемента DOM, основанного на классе, измененном другой директивой: http://jsfiddle.net/travisgosselin/sx7jponj/1/ В этом примере используется Angular 1.2.25.

 scope.$watch(function () {
        return {
            width: element.closest('.checkSize').width(),
            height: element.closest('.checkSize').height()
        };
    }, function (size) {
        scope.height = size.height;
    }, true);

Другой jsfiddle, который точно такой же, но с Angular 1.3.0, вы заметите, что часы не запускают обновление, поскольку класс, кажется, применяется после того, как произошло $watch, не отображая обновления размера элемента. http://jsfiddle.net/travisgosselin/t80segou/1/

scope.$watch(function () {
        return {
            width: element.closest('.checkSize').width(),
            height: element.closest('.checkSize').height()
        };
    }, function (size) {
        scope.height = size.height;
    }, true);

Идея заключается в том, чтобы позволить одной из моих директив изменять размер независимо от того, что происходит в другом компоненте.

В журнале изменений Angular единственное умеренно связанное изменение, которое я вижу, касается ngAnimate. См. критические изменения в версии 1.3.0-rc.5: API класса $animate CSS всегда будет откладывать изменения до конца следующего дайджеста. Это позволяет ngAnimate объединять изменения класса, которые происходят в течение короткого периода времени, в 1 или 2 записи DOM, а не во множество. Это предотвращает зависания в браузерах, таких как IE, и в целом это хорошо. Если вы обнаружите, что ваши классы не применяются немедленно, обязательно вызовите $digest().

Любая идея, как я могу лучше всего изменить этот сценарий, чтобы заставить часы на размер элемента dom срабатывать? На данный момент моей единственной альтернативой является использование серии событий, которые запускаются из разных мест и вызывают изменение размера (pub/sub).


person Travis    schedule 17.11.2014    source источник
comment
Вы можете запустить цикл дайджеста после того, когда вы вызываете changeSize(). Добавьте вызов $timeout(); в конце. Да, я знаю, это грязно…   -  person Blackhole    schedule 18.11.2014
comment
Спасибо за предложение Blackhole. Кажется, что все обходные пути в Angular начинаются с $timeout. Я попробовал это в своем приложении, и это сработало хорошо. Однако вы должны передать функцию $timeout, иначе произойдет ошибка, поэтому мне пришлось передать пустую функцию, что сделало ее еще более уродливой. При этом, это было настолько просто, что я использовал это как свою работу с большим количеством комментариев. Я действительно хотел бы понять, как справиться с этим сценарием в Angular или есть ли здесь ошибка (я думаю, в идеале я не должен был структурировать свои часы в директиве на основе размера элемента).   -  person Travis    schedule 24.11.2014
comment
Я также вижу случай, когда ng-class имеет состояние гонки и в конечном итоге применяет как старое, так и новое значение к dom, когда когда-либо должен применяться только один класс.   -  person Lukus    schedule 25.03.2015


Ответы (1)


Есть способ, если вы можете включить ngAnimate в свое приложение.

$animate.enabled(false, element) -- Активируйте этот метод внутри директивы changeclass, передав ссылку на элемент, к которому применяется ng-class

app.directive("changeClass", function ($animate) {
    return {
        restrict: 'A',
        scope: true,
        template: '<div><div ng-click="changeSize()">Change</div><div  ng-class="{ \'biggerSize\': biggerSize }" class="smallerSize checkSize"><div read-class></div></div></div>',
        replace: true,
        link: function (scope, element, attrs) {
            $animate.enabled(false, angular.element(element.children()[1]));
            scope.biggerSize = false;
            scope.changeSize = function () {
                scope.biggerSize = !scope.biggerSize;
            };
        }
    };
});

Рабочая скрипта

person Vinay K    schedule 29.03.2015
comment
Спасибо Винай! Интересно, что обходной путь действительно работает. На данный момент я уже реализовал некоторые другие обходные пути дайджеста. Надеялся получить более прямой ответ на этот вопрос. - person Travis; 07.04.2015