Javascript 将($compile)html从后端呈现到视图中,而不阻塞dom

Javascript 将($compile)html从后端呈现到视图中,而不阻塞dom,javascript,html,angularjs,dom,compilation,Javascript,Html,Angularjs,Dom,Compilation,上下文 我需要在我的AngularJS(v1.4)应用程序中加载一些从后端获取的HTML,并将其(HTML)插入我的(已加载的)应用程序中。该部分已经加载了一些HTML(并且完全可用)。现在,我可以加载HTML并使用此处发布的指令()编译它。请参阅下面的代码 问题 但是…当HTML的一部分已经加载(部分加载且功能正常),然后我从后端获得另一个HTML内容,并且指令正在编译新内容时,整个文档(DOM)就会“冻结”。我无法键入输入或单击按钮,包括我以前加载的HTML中的按钮 问题 我怎样才能加载HT

上下文

我需要在我的AngularJS(v1.4)应用程序中加载一些从后端获取的HTML,并将其(HTML)插入我的(已加载的)应用程序中。该部分已经加载了一些HTML(并且完全可用)。现在,我可以加载HTML并使用此处发布的指令()编译它。请参阅下面的代码

问题

但是…当HTML的一部分已经加载(部分加载且功能正常),然后我从后端获得另一个HTML内容,并且指令正在编译新内容时,整个文档(DOM)就会“冻结”。我无法键入输入或单击按钮,包括我以前加载的HTML中的按钮

问题

我怎样才能加载HTML内容,
$compile
在“后台”中加载它,或者以任何其他方式继续使用剩余的(已经运行的)HTML

对我来说,新的html内容必须得到编译,因为它包含角度验证等等,需要编译并进入“角度世界”(在角度世界中等等)

这是我用来编译html的指令

在控制器中,我有类似的内容

//如果我从服务中获取HTMLs,那么这将充满异步调用
//为了使这个例子简单,我只是做了一个演示,而不是真正的异步调用
$scope.secciones=[]
//当承诺得到解决时,“secciones”会是这样的(之后可以及时添加更多项目)
$scope.secciones=[
{html:“此处的一些html内容(有时不太小)”},
{html:“此处有另一个html内容(有时不太小)”}
]
…并且在视图中


注意:我使用这种方法是因为每个html代表我拥有的选项卡面板中的一个选项卡,用户实际上在“secciones”中只看到所有html中的一个(其他html被隐藏,但仍然存在),但我需要编译其他html,以便在用户单击其他选项卡时为其做好准备(secciones中的另一个html)


如果可以升级到AngularJS(1.x)的更新版本来解决这个问题,比如说1.6。我很乐意尝试一下。

基本上,我是通过从脚本标签获取html并编译它并附加到现有的div来完成的。 您可以使用以下代码段

在html中包含div

为了演示,这将包含在html页面中


通过这种方式,您可以编译来自后端的html


希望有帮助。

您可以尝试使用此指令编译HTML代码。当检测变量
htmlCode中的任何更改时,此指令将编译代码。

module.directive('bindHtmlCompile', ['$compile', function ($compile) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                scope.$watch(function () {
                    return scope.$eval(attrs.bindHtmlCompile);
                }, function (value) {
                    element.html(value && value.toString());
                    var compileScope = scope;
                    if (attrs.bindHtmlScope) {
                        compileScope = scope.$eval(attrs.bindHtmlScope);
                    }
                    $compile(element.contents())(compileScope);
                });
            }
        };
    }]);
您可以通过bower安装

用法:


我一试,就会给你一些反馈。非常感谢你的帮助!我一直在尝试你的解决方案,但我想我误解了$templateCache.get方法的作用。我想它会收到一些html内容(包括字符串html),但似乎只有文件中的htmll内容才有可能传递给该方法。我正在传递要呈现的html的字符串表示,但方法$templateCache.get返回未定义的内容,请参见我的devtools的此屏幕截图。“数据”是html字符串,template是$templateCache的返回值。get请查看您不必使用模板缓存,只需将html作为字符串传递。我已在此处注释//或您的html//这只是示例var template=“”或者当你从后端获取html时,将其添加到模板缓存中,然后从中接收感谢!但我无法在不影响页面可用性的情况下使其正常工作。我的问题的一个关键点是,当angular编译某些(新)html时,它不会阻塞页面的其余部分,并且可以“添加”我使用了另一个变量,根据并尝试使用
$templateCache.put(“myId”,data)
其中数据是我要呈现的新html,我将其放入html中
,但运气不好,tihs的行为方式与解决方案实际编译我的html并将其放入页面中的方式相同,但过程仍然冻结网页。
$(“#步骤容器”).show()
是否打算“集成”只有当新内容准备好时才可以使用它?可能我使用的不正确。再次感谢您的帮助!使用
$timeout
来包装模板的编译。这样您就不会阻止主线程,您的应用程序也会响应。还有$scope。$evalAsync.Ref:谢谢大家。使用我在问题中提到的指令,我做到了`scope.$evalAsync(function(){ele.html(html);$compile(ele.contents())(scope);})`和`$timeout(function(){ele.html(html);$compile(ele.contents())(scope);}`行为是相同的:(@ASIELLALCELDIRO也许你可以将你的指令代码添加到问题中,以便找到正确的答案solution@Kliment我添加了我在问题中最初提到的指令代码和我正在做的一个示例。希望它有助于澄清情况。任何其他问题,请随时提问。非常感谢您的帮助!谢谢@Isma90的帮助。我刚刚尝试了你的指令,但最终结果是一样的。当html有点大时,屏幕会像以前一样冻结。
// this will be filled with asynchronous calls were I get the HTMLs from a service
// in order to keep this example simple I just made a demo, not with the real async calls
$scope.secciones = []

//when the promises are getting resolved "secciones" would be something like (more items can be added after in time)
$scope.secciones = [
    {html: "<div> some html content here (not too small sometimes) </div>"},
    {html: "<div> another html content here (not too small sometimes) </div>"}
]
<!--every time an async call with html is resolved, it's added to secciones, then a new div is generated and compiled-->
<!-- if there was some html previously rendered and the app starts compiling new html the UI gets "freezed"-->
<div ng-repeat="item in secciones">
    <div dynamic="item.html"></div>
</div>
<div id="step-container">

</div>
var template = $templateCache.get('basicInfo'); // or your html
$compile($("#step-container").html(template).contents())($scope);
$("#step-container").show();
<script type="text/ng-template" id="basicInfo"></script>
module.directive('bindHtmlCompile', ['$compile', function ($compile) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                scope.$watch(function () {
                    return scope.$eval(attrs.bindHtmlCompile);
                }, function (value) {
                    element.html(value && value.toString());
                    var compileScope = scope;
                    if (attrs.bindHtmlScope) {
                        compileScope = scope.$eval(attrs.bindHtmlScope);
                    }
                    $compile(element.contents())(compileScope);
                });
            }
        };
    }]);