AngularJS实现动态模板 - 确认对$ compile和link的理解

时间:2014-09-02 17:35:23

标签: javascript angularjs

我正试图在高层次上理解动态templateUrl,因为我刚刚开始使用AngularJS。我在GitHub上发现了这个project,这正是我想做的事情。在片段下方,我添加了一些关于我对$ compile和link执行流程的理解的文本,以确保我理解它(一般AngularJS编译然后应用到片段)。

    .directive('formField', [ '$http', '$compile', function( $http, $compile ) {

    var getTemplateUrl = function( field ) {
        var type = field.field_type;
        var templateUrl = '';

        switch( type ) {
            case 'textfield':
                templateUrl = 'components/form-field/textfield.html';
                break;
            case 'email':
                templateUrl = 'components/form-field/email.html';
                break;
            // etc...
        }

        return templateUrl;
    }

    var linker = function( scope, element ) {

        var templateUrl = getTemplateUrl( scope.field );
        $http.get(templateUrl).success(function(data) {
            element.html(data);
            $compile(element.contents())(scope);
        });
    }

    return {
        restrict: 'E',
        replace: true,
        scope: {
            field: '='
        },
        link: linker
    }
}]);

我理解指令和控制器的基础知识,以及隔离范围在双向数据绑定和模块重用方面的使用。因此,我理解$ compile和link,如果我错了,请纠正我:

  • ng-app创建$ rootScope,并开始编译DOMElements,其中包括编译和链接
  • $ compile遍历DOMElements(显然与其他框架不同???)
  • $ compile正在寻找指令,当发现这些指令被推送到列表以便对其编译函数进行排序和执行时
  • $ compile返回一个链接函数...然后将其转换为另一个链接函数并返回并执行
  • 链接器传递所需的绑定范围,并递归执行子链接函数
  • 链接器返回一组数据绑定的DOMElements,其中包含用于交互的附加侦听器,并最终附加到父节点

所以在上面的例子中,我正在创建和元素指令,替换DOM中的指令标记,附加隔离范围以重用表单字段,以及附加链接器函数,该函数将以递归方式被调用。它耗尽并基于我传递的隔离范围并使用注入的$ http来抓取我的templateUrl。然后使用带有.html()的jQuery别名元素,并将内容设置为返回的模板。模板是通过抓取所有子进程并通过param编译来编译的。哪个会返回一个链接函数,然后用范围调用第二个链接函数...正确吗?

这仍然是实现动态模板的最佳方式吗? Stackoverflow中的大多数示例都是相似的,但似乎都已有两年了,这意味着它们将是AngularJS-1.2之前的版本。

更新 下面使用ng-include by @ user3677563提供的示例似乎是一个更好的实现,从我的初级角度眼睛。上述代码与ng-include示例的用例是什么?寻找利弊(即表现)以及我将来可能会实现上述代码段的内容。还有我对$ compile和link的理解吗?

1 个答案:

答案 0 :(得分:1)

为此,我会推荐ngInclude指令https://docs.angularjs.org/api/ng/directive/ngInclude

您只需创建一个ng-include元素或将其添加为属性以及提供源字符串属性,它将自动为您提取和缓存html。

要使用fieldproperty实现此功能,您可以在控制器上添加getTemplateUrl函数并将其提供给ngInclude指令。

像这样:

<ng-include url="getTemplateUrl(field)"></ng-include>