加速 Angular 的 $compile 函数

4

我正在手动编译一个模板,针对一个新的作用域:

var scope = _.assign($rootScope.$new(true), {
  foo: 1,
  bar: 2
})
var element = angular.element('<my-element foo="foo" bar="bar"></my-element>')
$compile(element)(scope)
element.appendTo(container)

运行基本的代码分析后,这段代码最慢的部分是$compile,每次编译需要1毫秒左右。我需要一次性编译大约100个元素,当用户滚动时。

在第一轮$compiles之后,我可以使用许多优化来加速编译,但我想要加速前100次编译。我也希望将模板保留在Angularland,避免注入原始HTML。

如何实现?

编辑:为了方便今后任何看到这个帖子的人,请把我的下面评论复制+粘贴到这里:

好吧,现在终于有点明白了。如果您将函数作为第二个参数传递给$link,angular将为您克隆节点。否则,它将在每次调用$link时重用相同的节点。无论哪种方式,您都可以在同步(作为$link的返回值)和异步(在回调内部)中访问返回的节点。这是一个设计不良的API,我在Angular的问题跟踪器中提出了一个问题 - github.com/angular/angular.js/issues/11824。


你想要像ng-repeat一样将100个元素编译或链接到作用域吗? - Chandermani
1个回答

9
如果这些元素具有相同的结构,只是在它们所链接的范围上有所不同,那么您应该仅对模板进行一次编译,然后使用link将这100个元素分别链接到它们各自的作用域中。
var myElement = angular.element('<my-element foo="foo" bar="bar"></my-element>');
var myElementLinkFn = $compile(myElement);


// "items" here is the data that drives the creation of myElement elements
angular.forEach(items, function(item){
   var newScope = $scope.$new(true);

   newScope.foo = item.foo;
   newScope.bar = item.bar;

   myElementLinkFn(newScope, function(clone){
      container.append(clone);
   })
});

做到了!好建议! - bcherny
我遇到了另一个性能问题:由于克隆是异步返回的,将克隆添加到我的容器所需的时间高度可变。是否有同步API可以获取克隆? - bcherny
@bcherny,'clone' 同步返回。 - New Dev
啊,没错。看了一下$compile的代码,似乎一个$compile调用只能映射到一个元素 - 没有办法从单个调用中生成多个元素。对于一个元素的多个link调用将共享同一个元素。 - bcherny
好的,现在终于有意义了。如果你将一个函数作为第二个参数传递给$link,angular会为你克隆节点。如果不这样做,它将在每次调用$link时重复使用相同的节点。无论哪种方式,你都可以同步地访问返回的节点(作为$link的返回值),也可以异步地访问它(在回调函数中)。这是一个设计不良的API,我在Angular的问题跟踪器中提交了一个问题 - https://github.com/angular/angular.js/issues/11824 - bcherny
1
@bcherny,我认为你在这里有些混淆了。如果传递所谓的cloneConnectFn,则该函数将获得已编译节点的克隆。然后,您可以自由地将其附加到DOM中,例如element.append(clone)。链接函数的结果是相同的DOM元素克隆,在链接之后。所有这些都是同步发生的。如果传递cloneAttachFn,则它会生成一个克隆 - 否则,它会链接您编译的节点。这是一个演示 - New Dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接