2016-11-01 3 views
1

У меня есть директива аватара пользователя, которая применяет цвет к нескольким путям в изображении SVG по предпочтению пользователя. Он применяется к каждому комментарию в потоке, который может быть очень длинным, и скомпилирован для каждого пользователя с несколькими комментариями.Как я могу кэшировать директиву AngularJS, которая вызывается повторно для одного и того же пользователя?

Вот сокращенная версия:

angular.module('someModule') 

.directive('userAvatar', ['$timeout', '$http', function ($timeout, $http) { 

    return { 
     restrict: 'E', 
     replace: true, 
     template: '<object type="image/svg+xml" data="/path/user-avatar.svg"></object>', 

     link: function (scope, element, attrs) { 
      scope.image = attrs.image; 

      var init = function() { 
       $timeout(function() { 

        var img = scope.image; 
        var path1, path2, path3; 

        // here we apply fill color to the paths by path ID 
       }, 0); 
      }; 

      var waitForRender = function() { 
       if ($http.pendingRequests.length > 0) { 
        // wait for all templates to be loaded 
        $timeout(waitForRender); 
       } else { 
        init(); 
       } 
      }; 

      $timeout(waitForRender); 
     } 
    }; 
}]); 

Предполагая, что мы можем передать идентификатор пользователя для каждого комментария, как я мог бы кэшировать выход директивы, который составляет в стилизованные графики SVG, для каждого уникального идентификатора?

ответ

0

Вы можете сделать это так же, как и с любой библиотекой JavaScript. Создайте объект, запишите его как значение с вашим параметром в качестве ключа. Затем, когда вам это нужно, посмотрите, есть ли он там, и используйте его вместо регенерации.

var cache = {}; 

link: function (scope, element, attrs) { 
    // ... 
    var id = getUserIdSomehow(); 

    if (!cache[id]) { 
     cache[id] = createNewImage(id); 
    } 

    return cache[id]; 
    // ... 
} 

Неточный код, очевидно, только псевдокод для иллюстрации. В принципе, есть переменная, будь то в масштабе или на глобальном уровне (в зависимости от вашего конкретного случая использования), и просто сохраняйте в ней созданные изображения, чтобы вы создавали их только в том случае, если у вас их еще нет.

+0

Спасибо. Это то, что я имел в виду, но я не понимаю, как скомпилировать шаблон директивы и сохранить его. Не могли бы вы усилить свой ответ, чтобы ответить на этот шаг? – isherwood

+0

Кроме того, где хранится 'cache'? Я экспериментировал с чем-то похожим с помощью '$ rootScope'. Очевидно, что он должен существовать вне сферы действия директивы. – isherwood

+0

А, я не выглядел достаточно близко к вашему примеру. Я не понимал, что ваша директива также имеет шаблон svg напрямую. Вероятно, вам захочется кэшировать его как часть другой директивы, а затем использовать его для отображения SVG (в основном он имеет шаблон «

{vm.userAvatar}
» и обрабатывает сам SVG как переменную, а не компонент. – samanime

1

$cacheFactory может сделать работу $cacheFactory.

Или service как единый объект также может использоваться для кеширования, поскольку service в отличие от controller не разрушается, когда вид отсутствует.

Основываясь на ваш комментарий, вы можете сделать следующее:

Создать свой пользовательский кэш завод. Имейте в виду, что этот завод будет вид постоянного хранения (до тех пор, пока не будет закрыто окно/вкладку)

angular.module('someModule').factory('superCache', ['$cacheFactory', function($cacheFactory) { 
    return $cacheFactory('super-cache'); 
}] 

Затем вводят superCache в вашу директиву. В вашей функции директивной ссылки вы можете сделать что-то вроде:

var dataUsedInTemplate; 
if(superCache.get(uniqueID)){ 
    // getting cached data if we already have it 
    dataUsedInTemplate = superCache.get(uniqueID); 
}else{ 
    // oops, we don't have data for this user yet, let's put it together 
    dataUsedInTemplate = createUserSpecificTemplateData(uniqueID); 

    // cache data for later use 
    superCache.put(uniqueID, dataUsedInTemplate); 
} 
+0

Что это данные, которые вы хотите кэшировать? 'scope.image'? Вы не можете хранить скомпилированный шаблон, он будет перекомпилирован в каждом цикле дайджеста. – oKonyk

+0

Это будет элемент объекта из шаблона после того, как стиль был применен к его дочернему пути Элементы – isherwood

+0

Я вижу ... Пожалуйста, см. обновленный ответ. Если вам нужна дополнительная помощь, поместите свой образец кода в Plunker и поделитесь ссылкой. – oKonyk

0

Я бы написал службу, которая управляет настройками пользователя. Таким образом, вы можете изменить реализацию в будущем по мере необходимости, не касаясь своей директивы. Возможно, вы захотите сохранить это в базе данных или по адресу $cookies, если этот параметр не требуется постоянно работать.

+0

Спасибо за ответ. Мне нужно немного подробнее, чтобы понять ваше предложение, но в этом случае есть загружаемые комментарии, которые не связаны с пользователем, прошедшим аутентификацию. – isherwood

0

Возможно, вы сможете делать то, что хотите, с помощью CSS и ng-include. Как предполагали другие, если ваши вычисления, для которых пользователи получают цвета аватара, очень сложны или связаны с вызовами AJAX, вы можете сохранить значения для быстрого поиска в будущем.

В приведенном ниже коде есть функция, которая будет делать это: сначала она проверяет, был ли пользователь «тип» уже рассчитан, и если он не выполняет его и вычисляет.

В зависимости от класса SVG он будет иметь разные цвета, которые вы задали в CSS. Ng-include будет вставлять разметку SVG непосредственно в DOM, чтобы вы могли манипулировать им с помощью CSS.

E.g.

наценки:

<ng-include class="avatar" 
    src="/path/user-avatar.svg" 
    ng-class="getUserType(user)"></ng-include> 

CSS:

.avatar.type-a path1{ 
    fill: red; 
} 
.avatar.type-a path2{ 
    fill: white; 
} 
.avatar.type-a path3{ 
    fill: blue; 
} 

.avatar.type-b path1{ 
    fill: red; 
} 
.avatar.type-b path2{ 
    fill: green; 
} 
.avatar.type-b path3{ 
    fill: yellow; 
} 

JS:

app.controller('MyController', ['$scope', function($scope){ 

    $scope.getUserType = function(user){ 
     // Don't recalculate the class for this user if you've already done it 
     if(typeof user.type !== 'undefined'){ 
      return user.type; 
     } 
     // This is where your logic goes if you need to calculate the user type 
     else if(user.ID == 1){ 
      user.type = 'type-a'; 
     } 
     else{ 
      user.type = 'type-b'; 
     } 
     return user.type; 
    } 

}]); 
+0

Является псевдокодом 'currentColor' или откуда он? – isherwood

+0

'currentColor' не является псевдокодом - он применит любой текущий стиль' color' к рассматриваемому правилу. В этом случае «fill» наследует то же значение, что и «color». См. Здесь лучшее объяснение: https://developer.mozilla.org/en/docs/Web/CSS/color_value#currentColor_keyword – Stafree

+0

Я вижу. Как мне применить 3 разных цвета к 3 различным путям в аватаре пользователя с этим подходом? – isherwood

Смежные вопросы