简体   繁体   English

如何在angularjs中延迟加载指令?

[英]How can directives be lazy loaded in angularjs?

I'm working with angularjs and I want to be able to load directives as and when they are needed instead of having all of them loaded at the start of the page. 我正在使用angularjs,我希望能够在需要时加载指令,而不是在页面开头加载所有指令。 I'm trying to create directives for my most frequently used plugins. 我正在尝试为我最常用的插件创建指令。

In this way, one direct can use yepnope to load all needed directives before finally compiling the html. 通过这种方式,一个直接可以使用yepnope加载所有需要的指令,然后再编译html。

If the directive is loaded at start of page with the others, everything works just fine. 如果指令是在页面的开头与其他指令一起加载的,那么一切正常。 However if the 'child' directive is loaded later (within the 'parent'), it does not take effect. 但是,如果稍后加载'child'指令(在'parent'中),它将不会生效。 Below is the code for the pre field in the compile field of the 'parent' directive. 下面是'parent'指令的compile字段中pre字段的代码。

    ...
    var pre = function (scope, element, attrs) {
        element.html('Please wait. Loading...');
        ang.loadDirectives('caiDatePicker', function () {
            console.log('loaded');
            scope.data.raw = scope.rawData;
            var html = createObjUi(scope, scope.data, scope.defn);
            element.html(html); //data
            $compile(element.contents())(scope.$new());
            scope.$apply();
        });
    };
    return { restrict:'A', compile: {pre:pre,post:function(){...}};

ang.loadDirectives loads the directive using yepnope. ang.loadDirectives使用yepnope加载指令。 Part of the code for the 'child' directive is as follows: 'child'指令的部分代码如下:

angular.module('mycomponents') //PS: I'm assuming this will fetch the already created module in the 'parent' directive
.directive('caiDatePicker', function ($parse) {
    return {
        scope: {},
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$watch('this.$parent.editing', function (v) {
                scope.editing = v;
            });
            yepnope({
                test: $().datePicker,
                nope: [
                    '/content/plugins/datepicker/datepicker.js', //todo: use the loader
                    '/content/plugins/datepicker/datepicker.css'
                ],
                complete: function () {
                    if (scope.model && scope.model.value) {
                        var date = scope.model.value;
                        element.val(date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear());
                    }
                    element.datepicker({ weekStart: 1, format: 'dd/mm/yyyy' })
                        .on('changeDate', function (ev) {
                            scope.model.value = ev.date;
                            scope.$apply();
                        });
                }
            });
            attrs.$observe('path', function (v) {
                var fn = $parse(v);
                var model = fn(scope.$parent);
                scope.model = model;
            });
        }
    }
});

Is what I'm doing even possible in the first place? 我首先做的是什么?

If so, what am I doing wrong? 如果是这样,我做错了什么?

If you want to register directives, after the application has been bootstrapped, you will have to use the $compileProvider instead of the module API. 如果要注册指令,则在引导应用程序之后,您将不得不使用$ compileProvider而不是模块API。 For example... 例如...

$compileProvider.directive('SomeLazyDirective', function()
{
    return {
        restrict: 'A',
        templateUrl: 'templates/some-lazy-directive.html'
    }
})

Then you can use the 'resolve' function when defining a route with the $routeProvider to load the lazy directive using your script loader. 然后,在使用$ routeProvider定义路由时,可以使用'resolve'函数来使用脚本加载器加载惰性指令。 To do this, let the function return a promise that is resolved once your directive and other lazy dependencies have been loaded. 为此,让函数返回一个在加载了指令和其他惰性依赖项后解析的promise。 AngularJS will wait for the promise to be resolved before rendering the route, thus ensuring that your directives will be ready before the view needs it. AngularJS将在呈现路由之前等待承诺得到解决,从而确保您的指令在视图需要之前就已准备就绪。 I have written a blog post detailing how to achieve lazy loading in AngularJS. 我写了一篇博文,详细介绍了如何在AngularJS中实现延迟加载。 It describes in more detail what I have stated here and it can be found at http://ify.io/lazy-loading-in-angularjs/ 它更详细地描述了我在这里所说的内容,可以在http://ify.io/lazy-loading-in-angularjs/找到它。

Here's what I did, using compile provider attached to the application, making it accessible from anywhere you have the actual module reference. 这是我所做的,使用附加到应用程序的编译提供程序,使其可以从具有实际模块引用的任何地方访问。

var app = angular.module('app');
app.config(function ($compileProvider) {
    app.compileProvider = $compileProvider;
});

Then later on, after bootstrap you can lazily load a directive which gets compiled and linked: 然后,在bootstrap之后,你可以懒洋洋地加载一个被编译和链接的指令:

app.compileProvider.directive('SomeLazyDirective', function()
{
    return {
        restrict: 'A',
        templateUrl: 'templates/some-lazy-directive.html'
    }
})

After searching for so long and not getting any answers, I ended up with the following 在搜索了这么久而没有得到任何答案后,我最终得到了以下内容

  1. Create an angular app. 创建一个角度应用。 This is also an angular module. 这也是一个角度模块。
  2. You can add any directive to the module at any time using app.directive(name,function). 您可以使用app.directive(name,function)随时向模块添加任何指令。 These can be directives loaded asynchronously. 这些可以是异步加载的指令。
  3. You can bootstrap any element. 你可以引导任何元素。 When bootstrapping, specify the app in the list of modules to angular. 引导时,将模块列表中的应用指定为angular。

The problem was that yepnope was not firing the complete function as I needed them to be. 问题是,yepnope没有按照我的要求发射完整的功能。 In the end, I build a small wrapper on top of yepnope that appears to guarantee that the complete function is fired. 最后,我在yepnope上构建了一个小包装器,似乎可以保证完整的功能被触发。

Final code looks something like: 最终代码类似于:

var app3 = new Cai.AngApp('app3');
app3.loadControllers('app1.controller3', function () {
        app3.loadDirectives('jsonEditor', 'datePicker', function () {
            app3.bootstrap($('#d3'));
    });
});

I am not sure how using a angularJS directive will be an appropriate answer 我不确定如何使用angularJS指令是一个合适的答案

I have done the following and it works flawlessly 我做了以下工作,它完美无瑕

  • Use mustache list to decide list item template.( https://github.com/janl/mustache.js/ ) 使用小胡子列表来决定列表项模板。( https://github.com/janl/mustache.js/
  • On load of your application apis should load only 10 -50 records, depending on your content. 在加载应用程序时,apis应该只加载10到50条记录,具体取决于您的内容。
  • On scroll of list as soon as you are about to reach to end, fire next apis call form next 20 items and so on. 在您即将结束时,在列表滚动中,接下来的20个项目点击下一个apis呼叫表格,依此类推。
  • If your data is not changing, you can store it locally and repopulate. 如果您的数据没有变化,您可以在本地存储并重新填充。

  • keep fetching latest records and ad it locally. 继续获取最新记录并在本地广告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM