AngularJS异步指令编译

AngularJS asynchronous directive compilation

本文关键字:编译 指令 异步 AngularJS      更新时间:2023-09-26

我正在编写一个angularjs应用程序(带有节点/快速后端(。在我的范围内,我有一个通过服务异步填充(和重新填充(的对象。

对象

的内容是一系列"问题"对象,为简单起见,它们具有"文本"和"类型"属性。

我试图实现的是能够为每个类型提供一个角度指令,并使其正确呈现。例如,如果服务器返回 [{type:'booleanquestion',text:'the sky is blue?'}]我会创建一个元素,然后布尔问题指令将启动并适当地呈现它。

到目前为止,我已经定义了一个运行良好的"问题集"指令,观察问题收集并编译所需的内容,以便指令显示 correclt.y

目录

<div questionset="questions"/>

应用.js

...
scope.questions = questions; // e.g. [{text: 'some text',type: 'boolean'}]

指令.js

angular.module('myApp').directive('questionset',function($compile){
    return {
        transclude: 'true',
        compile: function(element,attr,linker){
            return function($scope,$element,$attr){
                var elements = [],
                    parent = $element.parent();
                $scope.$watchCollection('questions',function(questions){
                    var block, i, childScope;
                    if(elements.length > 0)
                    {
                        for( i = 0; i < elements.length ; i++)
                        {
                            elements[i].el.remove();
                            elements[i].scope.$destroy();
                        }
                        elements = [];
                    }
                    if(!questions) return;
                    for(i = 0; i < questions.length; i++)
                    {
                        childScope = $scope.$new();
                        childScope['question'] = questions[i];
                        var html = '<div class="'+questions[i].type+'"/>';
                        var e = angular.element(html);
                        block = {};
                        block.el = e;
                        block.scope = childScope;
                        $compile(e)(childScope);
                        element.append(e);
                        elements.push(block);
                    }
                });
            }
        }
    }
});
// For example, one type might be "boolean"
angular.module('myApp').directive('boolean',function($compile){
    return {
        restrict: 'AC',
        template: '<div class="question">{{question.text}}</div>',
        replace: true,
        link: function(scope,elem,attrs,ctrl){
            …….
       // for some reason, $compile will not be defined here?
        }
    };
});

虽然这工作正常,但我有 2 个问题

1(. 这是"正确"的角度方法吗?这是我的第一个角度项目,似乎我已经跳进了深渊(或者无论如何就是这样感觉(

2(. 我的下一个目标是让 question.text 能够包含 HTML 并对其进行"编译"。例如,文本可能是

"Is the <strong>sky</strong> blue?"

我不确定如何使这项工作 - 正如我在代码中的注释所暗示的那样,由于某种原因,$compile没有注入到我的布尔指令中。也许这是因为我已经手动为其创建了该子范围?我试图再次$compile元素的内容是对的吗?我觉得最后一点可能很简单,但我没有看到它。

1(我不知道。在我看来,整体方法似乎非常好;只需要润色它,我们将在下面看到。

2(也许$compile在嵌套函数中不可用,因为它不在父级别中使用。尝试在父函数中引用$compile,看看这是否真的是原因:

angular.module('achiive-vision').directive('boolean',function($compile){
    var justTesting = $compile;
    return {
        restrict: 'AC',
        template: '<div class="question">{{question.text}}</div>',
        replace: true,
        link: function(scope,elem,attrs,ctrl){
            …….
       // check if $compile is defined here now
        }
    };
});

我会通过将questionset元素 html 更改为:

var html = '<div class="question ' + questions[i].type + '">'
           + questions[i].text + '</div>';

这样,您就不需要再次编译,并且已经拥有HTML支持。

另外,拥有它有点奇怪

var html = '<div class="'+questions[i].type+'"/>';

以上,然后您将用类似的标记替换它:

template: '<div class="question">{{question.text}}</div>',

。然后你想再次编译它...

在我看来,你不需要replace: true,也不需要问题类型指令的template。实现行为和它们的其他任何内容,但让父questionset包含问题文本并编译它 - 一切都准备好了。

另外,还有一个细节:我不会在循环中var htmlvar e。我会将它们添加到上面的列表中:

var block, i, childScope, html, e;

(另外,我会避免将变量命名为"i"和"e"......

这些是我对你的代码的评论。正如我所说,我认为这种方法非常好,而不是说"高级"对于开始使用AngularJS的人来说。我自己使用它不到两个月,只有