是否可以创建一个充当单例的指令?

时间:2015-04-16 19:42:10

标签: javascript angularjs

我们有一个指令作为我们的大型单页面应用程序的一部分。我们在页面上的多个位置使用相同的指令,并且每次操作时看起来完全相同。我们看到的主要问题是这个指令有一个ng-repeat,可以创建几百个DOM元素。

是否可以创建一个充当单例的指令?即每次使用该指令时,只在集合上有一个监视而不是监视,或者缓存DOM元素的创建以提高速度。或者是否有更好的方法在同一页面中多次使用相同的DOM元素。

我一直在考虑使用自定义ng-repeat来缓存创建的html并重复使用它,这是最好的方法吗?

3 个答案:

答案 0 :(得分:3)

Angular在"服务"中有一个单例概念。零件。你不能制作指令单身(没有hackery),但你可以完全使服务这样做 - 因为它们已经存在。我接近这个的方法是让服务完成数据工作并将其暴露给指令。指令只是访问服务,因为服务已经是单例,它们都将共享一个数据对象/集合/模型。

答案 1 :(得分:2)

当然,有可能,在某种程度上。这是an example fiddle

app.directive('sample', function ($compile, $timeout) {
  var cached;

  return {
    scope: { sampleData: '@', sampleArray: '=' },
    // simple counter for bindings
    controller: function ($scope) {
      $scope.getSampleData = function () {
        console.log('getSampleData');
        return  $scope.sampleData;
      };
    },
    // no overhead for nested directives
    terminal: true,
    template: '<div ng-repeat="n in sampleArray">{{n}} {{::getSampleData()}}</div>Hi! {{::getSampleData()}}',
    compile: function (element) {
      // keeping it wrapped into single element may save you from surprises
      var contents = angular.element('<div>').append(element.contents());
      element.empty();

      return function (scope, element, attrs, ctrl) {        
        cached = cached || $compile(contents)(scope);

        // there's no interpolated template available in post-link, so
        $timeout(function () {
          element.append(cached.clone().contents());
        });

      };
    }
  };
}); 

无法控制编译阶段,但可以在可能的情况下将缓存模板提供给指令。 您也可以考虑使用缓存服务而不是本地变量。

没人能保证它不会引起问题。除非您已经遇到性能问题并应用了其他优化技巧(我个人found这些ones非常inspiring),所以上述方法应被视为过早优化的特殊情况(即致命的罪。)

答案 2 :(得分:1)

如果您对ng-repeat生成的手表数量有问题,则应使用bindOnce directive(已在角度1.3中本机实现)。

如果您在渲染时遇到问题,可以考虑使用ReactJS

之类的替代渲染器