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

Javascript 延迟加载:在HTML呈现之前需要JS,javascript,angularjs,requirejs,lazy-loading,Javascript,Angularjs,Requirejs,Lazy Loading,我正在使用RequireJS加载JS,但HTML部分不会等待所需的JS指令 开始加载JS 呈现HTML(带指令) 完成JS,然后定义指令(Oops太晚了,已经呈现HTML) 我允许SPA中的“插件”允许我加入新的实体(HTML+JS)。HTML是通过控制器加载的(在本例中是通过指令链接中的“$templateFactory.fromUrl()”),相应的JS包含在该HTML部分中 function inputFrequencyDirective($templateFactory, $compil

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

  • 开始加载JS
  • 呈现HTML(带指令)
  • 完成JS,然后定义指令(Oops太晚了,已经呈现HTML)
  • 我允许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):

    这个解决方案很简单,并且与标准框架配合使用效果很好,但是使用async RequireJS,我遇到了一个排序问题。如果我将频率类型切换为“daily”,然后再切换回“weekly”,HTML将正确呈现,因为weekly.js中的指令确实已注册,但对于第一次weekly.HTML呈现来说太晚了

    我基本上希望在脚本完成之前“等待require完成”(从而延迟HTML呈现)。最好的方法可能是用一个“ngif”元素包围HTML,并通过在Weekly.HTML的脚本“require”块中“truificationthengif”来启用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>
    
    
    var someflag=false;
    要求(['angular','weekly'],函数(angular){
    someflag=true;
    });
    周报
    每(星期几)
    
    我正在使用当前版本:
    angular 1.4.8、uiRouter 0.2.17、requireJS 2.2.0

    我尝试了很多方法来阻止requireJS异步加载上的/event/semaphore,但都没有成功

    然后,我将IIFE放在包含的部分中,使整个解决方案同步。我也通过实施一些其他更改(例如:简化include指令以使用ng include,删除脚本处理指令以让jquery完成这项工作,…)

    下面是最后一个同步延迟加载HTML/脚本部分的Plunk:

    
    (功能(角度){
    [..]
    })(角度);
    周报
    每(星期几)
    

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

    看看这个回购协议,它的工作原理要简单得多。下面是完整的消息,删除的评论有一个很好的轮询循环。我试着让我的思想围绕着这样一个事实:我有一个包含HTML和JS的文件。。。我需要延迟HTML本身。使用超时/事件很好,但我确实需要阻止,直到RequireJS函数设置标志。我真的很想在这里使用事件并启用HTML块(ng if),但我不知道如何从标准Javascript访问它(同时我正在查看ocLazyLoad,看看它是否能提供类似的简单解决方案)。在ocLazyLoad示例中,看起来我必须声明/加载所有依赖项(例如:manifest)事先把它们都装进去。请注意,在我的Plunk中,我想让HTML部分作为入口点,它将知道并使用标准的require/angular框架处理自己的依赖关系。老实说,我认为惰性地注册指令是浪费时间。当然,您可能想要延迟加载库,并且您应该这样做,例如,如果您仅在一个页面或指令中使用d3.js。为什么不呢?也许您可以模块化您的代码,甚至延迟加载包含许多指令的模块。
    function (angular) {
        var app = angular.module('myApp');
        app.lazy.directiveRegister('frequencyWeeklyInputDay', [function () {
        [...]
    
    <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>
    
    <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>