返回介绍

Compile 的细节

发布于 2024-12-24 22:41:42 字数 8485 浏览 0 评论 0 收藏 0

18.5. Compile的细节

指令的处理过程,是 ng 的 `Compile` 过程的一部分,它们也是紧密联系的。继续深入指令的定义方法,首先就要对 Compile 的过程做更细致的了解。

前面说过, ng 对页面的处理过程:

  • 浏览器把 HTML 字符串解析成 DOM 结构。
  • ng 把 DOM 结构给 $compile ,返回一个 link 函数。
  • 传入具体的 scope 调用这个 link 函数。
  • 得到处理后的 DOM ,这个 DOM 处理了指令,连接了数据。

$compile 最基本的使用方式:

  var link = $compile('<p>{ { text } }</p>');
  var node = link($scope);
  console.log(node);

上面的 $compilelink 调用时都有额外参数来实现其它功能。先看 link 函数,它形如:

  function(scope[, cloneAttachFn]

第二个参数 cloneAttachFn 的作用是,表明是否复制原始节点,及对复制节点需要做的处理,下面这个例子说明了它的作用:

  <div ng-controller="TestCtrl"></div>
  <div id="a">A { { text } }</div>
  <div id="b">B </div>
  app.controller('TestCtrl', function($scope, $compile){
    var link = $compile($('#a'));

    //true参数表示新建一个完全隔离的scope,而不是继承的child scope
    var scope = $scope.$new(true);
    scope.text = '12345';

    //var node = link(scope, function(){});
    var node = link(scope);

    $('#b').append(node);
  });

cloneAttachFn 对节点的处理是有限制的,你可以添加 class ,但是不能做与数据绑定有关的其它修改(修改了也无效):

  app.controller('TestCtrl', function($scope, $compile){
    var link = $compile($('#a'));
    var scope = $scope.$new(true);
    scope.text = '12345';

    var node = link(scope, function(clone_element, scope){
      clone_element.text(clone_element.text() + ' ...'); //无效
      clone_element.text('{ { text2 } }'); //无效
      clone_element.addClass('new_class');
    });

    $('#b').append(node);
  });

修改无效的原因是,像 { { text } } 这种所谓的 `Interpolate` 在 $compile 中已经被处理过了,生成了相关函数(这里起作用的是 directive 中的一个 postLink 函数),后面执行 link 就是执行了 $compile 生成的这些函数。当然,如果你的文本没有数据变量的引用,那修改是会有效果的。

前面在说自定义指令时说过, link 函数是由 compile 函数返回的,也就像前面说的,应该把改变 DOM 结构的逻辑放在 compile 函数中做。

$compile 还有两个额外的参数:

  $compile(element, transclude, maxPriority);

maxPriority 是指令的权重限制,这个容易理解,后面再说。

transclude 是一个函数,这个函数会传递给 compile 期间找到的 directivecompile 函数(编译节点的过程中找到了指令,指令的 compile 函数会接受编译时传递的 transclude 函数作为其参数)。

但是在实际使用中,除我们手工在调用 $compile 之外,初始化时的根节点 compile 是不会传递这个参数的。

在我们定义指令时,它的 compile 函数是这个样子的:

  function compile(tElement, tAttrs, transclude) { ... }

事实上, transclude 的值,就是 directive 所在的 原始 节点,把原始节点重新做了编译之后得到的 link 函数(需要 directive 定义时使用 transclude 选项),后面会专门演示这个过程。所以,官方文档上也把 transclude 函数描述成 link 函数的样子(如果自定义的指令只用在自己手动 $compile 的环境中,那这个函数的形式是可以随意的):

  {function(angular.Scope[, cloneAttachFn]}

所以记住,定义指令时, compile 函数的第三个参数 transclude ,就是一个 link ,装入 scope 执行它你就得到了一个节点。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文