在不阻塞DOM的情况下,从后端渲染($compile)HTML到视图中。
在不阻塞DOM的情况下,从后端渲染($compile)HTML到视图中。
背景
我需要在我的AngularJS(v1.4)应用程序中加载一些从后端获取到的HTML,并将其插入到我的局部视图(已加载)。局部视图已经加载了一些HTML(并且完全可用)。目前,我能够加载HTML并使用此处发布的指令进行编译(Compiling dynamic HTML strings from database)。请参见下面的代码。
问题
但是...当部分HTML已经加载(局部视图已加载并可用),然后我从后端获取另一个HTML内容,并且该指令正在编译该新内容时,整个文档(DOM)被“冻结”了。我无法在输入框中输入文字或点击按钮,包括之前加载的HTML中的输入框和按钮。
问题
如何加载HTML内容,$compile
它在“后台”或任何其他方式,以便我可以继续使用其余(已经可用的)HTML?
对于我来说,新到达的HTML内容必须被编译,因为它包含需要被编译并进入“Angular世界”(在Angular的digest cycle中等等)的Angular验证等等。
这是我用于编译HTML的指令:
(function () { var dynamic = function($compile) { return { restrict: 'A', replace: true, link: function (scope, ele, attrs) { scope.$watch(attrs.dynamic, function(html) { if (html) { ele.html(html); $compile(ele.contents())(scope); } }); } }; }; dynamic.$inject = ['$compile']; angular.module('app') .directive('dynamic', dynamic); }());
在控制器中,我有类似以下的内容:
// 这将填充异步调用,从服务中获取HTML // 为了简化示例,我只是做了一个演示,而不是使用真正的异步调用 $scope.secciones = [] // 当承诺被解析时,“secciones”将是以下的形式(可以在之后添加更多项) $scope.secciones = [ {html: " 这里是一些HTML内容(有时不太小) "}, {html: " 这里是另一个HTML内容(有时不太小) "} ]
...在视图中
注意:我之所以使用这种方法,是因为每个HTML代表我拥有的选项卡面板中的一个选项卡,在其中用户实际上只看到“secciones”中的一个HTML(其他的是隐藏的,但仍然存在),但我需要编译其他的HTML,以便当用户点击其他选项卡(secciones中的另一个HTML)时,它们已经准备好供用户使用。
如果升级到更高版本的AngularJS(1.x),比如1.6,有任何解决方案,我很乐意尝试。
问题的出现原因是当从后端返回的HTML代码较大时,将其编译并渲染到视图中会导致页面卡顿。解决方法是使用上述提供的指令bindHtmlCompile
,该指令在检测到htmlCode
变量发生变化时,编译并渲染HTML代码。
为了解决这个问题,我们可以使用bindHtmlCompile
指令。该指令在链接函数中使用$watch
来监视htmlCode
变量的变化。当变量发生变化时,指令会将新的HTML代码赋值给元素的内容,并通过$compile
函数将其编译为可渲染的DOM元素。
使用bindHtmlCompile
指令的方法很简单。只需在HTML代码中添加<div bind-html-compile="htmlCode"></div>
即可。其中htmlCode
是从后端获取的HTML代码。
感谢您的帮助。我已经尝试了您提供的指令,但最终结果还是一样。当HTML代码较大时,页面仍然会卡顿。
问题的出现原因:当从后端获取的HTML内容需要在前端进行渲染时,使用AngularJS的$compile方法进行编译和插入DOM会导致页面阻塞,用户无法流畅地使用页面其他部分。
解决方法:可以通过以下步骤解决该问题:
1. 在HTML中添加一个容器div,用于显示后端返回的HTML内容。
2. 在控制器中使用$templateCache获取后端返回的HTML内容,并使用$compile方法进行编译。
3. 将编译后的HTML内容插入到之前添加的容器div中,并显示在页面上。
具体代码如下:
var template = $templateCache.get('basicInfo'); // or your html $compile($("#step-container").html(template).contents())($scope); $("#step-container").show();
通过以上方法,可以在不阻塞页面的情况下将后端返回的HTML内容进行编译和渲染。