Preloading HTML partials into AngularJS UI-Router

2020-03-20 05:39发布

I notice that on a full refresh of my angular app, state transitions (I am using ui-router but then may be similar to native Angular routing as well) have a slight lag on first visit because the browser does a GET request to retrieve the HTML partial that is associated with that given state. All subsequent visits are basically instantaneous, but I want to know if there is a way to tell Angular to pre-load all the needed partials when first coming to the page?

Do they not do this because eventually too many partials would use too much bandwidth if fetched in parallel?

3条回答
干净又极端
2楼-- · 2020-03-20 06:15

To preload templates at application initialization, you can use:

angular
.module('app')
.run(['$state', '$templateCache', '$http',
    function ($state, $templateCache, $http) {
        angular.forEach($state.get(), function (state, key) {
            if (state.templateUrl !== undefined && state.preload !== false) {
                $http.get(state.templateUrl, {cache: $templateCache});
            }
        });
    }
]);

This will preload all templateUrls by default unless preload: false is set in the state definition.

Thanks to Sobieck's answer here for the concept, which I modified for use with ui-router.

查看更多
放荡不羁爱自由
3楼-- · 2020-03-20 06:15

Here is a solution that will do just that and will handle any defined views.

run(['$state', '$templateCache', '$http', function($state, $templateCache, $http) {
    var url;
    function preload(v){
        if(v.preload){
            if(url = v.templateUrl){
                $http.get(url, { cache: $templateCache });
            }
        }
        // state has multiple views. See if they need to be preloaded.
        if(v.views){
            for(var i in v.views){
                // I have seen views with a views property.
                // Not sure if it's standard but won't hurt to support them
                preload(v.views[i]);
            }
        }
    }
    $state.get().forEach(preload);
}])

You can easily change this to preload by default by replacing line 4 (if(v.preload){) with if(v.preload === false){.

Based on this answer.

查看更多
The star\"
4楼-- · 2020-03-20 06:19

You could put those partials inside a script tag, and place it in your main HTML page so they're all loaded up front. You could also load them in the run block of your app, and put them in the $templateCache:

$templateCache.put('template.html', '<h1>My template</h1>');

Or get it from the server if it's not inline:

$http.get('template.html', {cache:$templateCache});

查看更多
登录 后发表回答