延迟加载:在HTML呈现之前需要JS

时间:2016-03-29 18:00:04

标签: javascript angularjs requirejs lazy-loading

我正在使用RequireJS加载JS,但HTML部分不会等待所需的JS指令....

  1. 开始加载JS
  2. 渲染HTML(带指令)
  3. 完成JS然后定义指令(糟糕太晚,已经呈现HTML)
  4. 我在我的SPA中允许“插件”允许我放入新实体(HTML + JS)。 HTML通过控制器加载(在本例中由指令链接中的“$ templateFactory.fromUrl()”加载),相应的JS包含在该HTML部分中。

    function inputFrequencyDirective($templateFactory, $compile) {
        return {
            restrict: 'E',
            scope: {},
            bindToController: {
                frequency: '=ngmodelFrequency',
            },
            compile: function CompilingFunction(element, attrs) {
                return function LinkingFunction($scope, $element, $attrs) {
                    var frequency = $scope.vm.frequency;
                    var type = frequency.type;
                    var promise = $templateFactory.fromUrl(type + ".html");
                    promise.then(function (template) {
                        var e = $compile(template)($scope);
                        $element.replaceWith(e);
                    });
                };
            },
    

    HTML部分(Weekly.html):

    <script type="text/javascript">
        // Async load "weekly.js"
        require(['angular', 'weekly'], function (angular) {
            console.log("weekly.html require complete");
        });
    </script>
    <h1>Weekly</h1>
    <div>
        <frequency-type-selector ngmodel-type="vm.frequency.type"></frequency-type-selector>
        <div><label>Every <frequency-weekly-input-day ngmodel-day="vm.frequency.day"></frequency-weekly-input-day> (day of week)</label></div>
    </div>
    

    JS包括(weekly.js):

    function (angular) {
        var app = angular.module('myApp');
        app.lazy.directiveRegister('frequencyWeeklyInputDay', [function () {
        [...]
    

    解决方案很简单,并且在标准框架下运行良好,但是使用异步RequireJS,我遇到了一个排序问题。如果我将频率类型切换为“每日”然后再切换回“每周”,则HTML会正确呈现,因为daily.js DID中的指令已注册,但对于第一个Weekly.html呈现来说太迟了。

    我基本上希望在脚本完成之前“等待require完成”(从而延迟HTML渲染)。最好的方法可能是使用一个“ng-if”元素包围HTML,并通过Weekly.html的脚本“require”块中的“验证ng-if”来启用HTML。这应该使元素在加载完成时正确呈现。

    我想知道“ng-if”的想法是否合理以及如何在非角度脚本块中进行。我不知道如何使用ng-if获取对建议元素的引用,或者如何从此可能共享控件的其他实例安全地执行此操作。

    建议 “概念”

    <script type="text/javascript">
        var someflag = false;
        require(['angular', 'weekly'], function (angular) {
            someflag = true;
        });
    </script>
    <h1>Weekly</h1>
    <div ng-if="someflag">
        <frequency-type-selector ngmodel-type="vm.frequency.type"></frequency-type-selector>
        <div><label>Every <frequency-weekly-input-day ngmodel-day="vm.frequency.day"></frequency-weekly-input-day> (day of week)</label></div>
    </div>
    

    我正在使用当前版本: 角1.4.8,uiRouter 0.2.17,requireJS 2.2.0

1 个答案:

答案 0 :(得分:1)

我在RequireJS的异步加载上尝试了许多阻止/事件/信号量的东西,但是无法使它工作。

然后我通过在所包含的部分中放置IIFE来使整个解决方案同步。我通过制定其他一些更改来完成所有工作(例如:简化了包含指令以使用ng-include,删除了我的脚本处理指令以让jquery执行它,...)。

这是最后的Plunk,可以同步延迟加载HTML /脚本部分:https://plnkr.co/edit/76feCbf15aJhYeJkS8VZ

<script type="text/javascript">
(function (angular) {
    [..]
})(angular);
</script>
<h1>Weekly</h1>
<div>
    <frequency-type-selector ngmodel-type="vm.frequency.type"></frequency-type-selector>
    <div><label>Every <frequency-weekly-input-day ngmodel-day="vm.frequency.day"></frequency-weekly-input-day> (day of week)</label></div>
</div>

我希望你觉得这个例子很有用。