使用 AngularJS 路由时有没有办法预加载模板?

Posted

技术标签:

【中文标题】使用 AngularJS 路由时有没有办法预加载模板?【英文标题】:Is there a way to preload templates when using AngularJS routing? 【发布时间】:2013-09-13 21:55:27 【问题描述】:

加载 Angular 应用程序后,我需要一些模板可以离线使用。

这样的事情会很理想:

$routeProvider
  .when('/p1', 
    controller: controller1,
    templateUrl: 'Template1.html',
    preload: true
  )

【问题讨论】:

Sobieck00 在此处给出了与原始问题***.com/a/23522925/956658相匹配的最佳答案@ 【参考方案1】:

这是@gargc 对答案的补充。

如果你不想使用脚本标签来指定你的模板,并且想从文件中加载模板,你可以这样做:

    myApp.run(function ($templateCache, $http) 
        $http.get('Template1.html',  cache: $templateCache );
    );

    myApp.config(function ($locationProvider, $routeProvider) 
        $routeProvider.when('/p1',  templateUrl: 'Template1.html' )
    );

【讨论】:

顺便说一句,$http.get('Template1.html', cache: $templateCache); 应该有同样的效果。虽然,它并没有太大的区别:) 这绝对是比我建议的更简单的选择。再次感谢:) 我更喜欢这个解决方案,因为它不需要从 HTML 模板构建 javascript 文件。 这一行“$http.get('Template1.html', cache: $templateCache );”也意味着你将它添加到角度缓存? 我已经尝试过了,但是由于 http.get 是异步的,我的模板还没有加载到我真正需要它的地方。有谁知道如何解决这个问题?【参考方案2】:

有一个模板缓存服务:$templateCache,可用于在 javascript 模块中预加载模板。

例如,取自文档:

var myApp = angular.module('myApp', []);
  myApp.run(function($templateCache) 
  $templateCache.put('templateId.html', 'This is the content of the template');
);

甚至还有一个从 html 文件预生成 javascript 模块的繁重任务:grunt-angular-templates

另一种可能不太灵活的方法是使用内联模板,例如,在 index.html 中包含这样的脚本标记:

<script type="text/ng-template" id="templates/Template1.html">template content</script>

意味着以后可以像路由配置中的真实 url 一样处理模板 (templateUrl: 'templates/Template1.html')

【讨论】:

谢谢,正是我想要的!我真的很希望能够在 $templateCache.put() 中指定模板文件,脚本标记替代项会弄乱我的 IDE,而且我没有使用 grunt。我最终使用了 $http。有关详细信息,请参阅我自己的答案。 我还没有测试过那个 Grunt 插件但是......它也包括控制器吗?还是只是模板?可能会很好地预加载所有可能的内容,以便快速加载视图。谢谢! +1 用于内联模板。内联模板允许更快的初始加载,但具有稍后替换内容的灵活性。 @derrylwc:我目前正在努力解决相反的问题。我有一个项目,使用 grunt 生成器(grunt-angular-fullstack)创建,它自动包含并配置了很多 grunt 任务。其中之一是 grunt-angular-templates。因为我想用我的身份验证框架拦截来自服务器的加载,所以我需要对服务器的请求,但我没有得到它们。所以是的,它还加载了 controller.js 文件。 如果您的模板需要从 URL 中获取:myApp.run(function($templateRequest) $templateRequest('/url/to/template.html', true); );【参考方案3】:

我认为基于 Raman Savitski 的方法,我对这个问题有一个稍微改进的解决方案,但它会选择性地加载模板。它实际上允许像这样要求的原始语法:

$routeProvider.when('/p1', controller: controller1, templateUrl: 'Template1.html', preload: true )

这允许您只装饰您的路线,而不必担心在其他地方更新另一个预加载配置。

这是在启动时运行的代码:

angular.module('MyApp', []).run([
    '$route', '$templateCache', '$http', (function ($route, $templateCache, $http) 
        var url;
        for (var i in $route.routes) 
            if ($route.routes[i].preload) 
                if (url = $route.routes[i].templateUrl) 
                    $http.get(url,  cache: $templateCache );
                
            
        
    )
]);

【讨论】:

如果有明确的preload: false,我会将其稍微更改为仅不预加载,因此默认情况下会为路由启用预加载。但我认为决定是个人品味,取决于你想做什么。除了那个伟大的sn-p! +1 当我写到我只是想加载大约 20 条左右的路线中的两条。所以,明确的preload: true 对我来说效果更好。 这是迄今为止最好的答案。 我很高兴在这里找到您的回复..我一直在努力寻找一种方法来缓存我的模板..谢谢 如果您像我一样来这里寻找使用 uiRouter 的解决方案并喜欢这个想法:try this。它将加载状态模板和它定义的任何视图。【参考方案4】:

预加载模块路由中定义的所有模板。

angular.module('MyApp', [])
.run(function ($templateCache, $route, $http) 
    var url;
    for(var i in $route.routes)
    
      if (url = $route.routes[i].templateUrl)
      
        $http.get(url, cache: $templateCache);
      
    
)

【讨论】:

如果模板内容动态变化会怎样?这是正确显示还是会显示与来自缓存的内容相同的内容? 如果内容是动态的 - “预加载”它是没有意义的。或者我不明白你的情况。【参考方案5】:

如果您将每个模板包装在脚本标签中,例如:

<script id="about.html" type="text/ng-template">
<div>
    <h3>About</h3>
    This is the About page
    Its cool!
</div>
</script>

将所有模板连接到 1 个大文件中。如果使用 Visual Studio 2013,下载 Web Essentials - 它添加了一个右键菜单来创建 HTML Bundle

添加这个人为更改 angular $templatecache 服务而编写的代码 - 它只是一小段代码,它可以工作:-)

https://gist.github.com/vojtajina/3354046

您的路线 templateUrl 应如下所示:

        $routeProvider.when(
            "/about", 
                controller: "",
                templateUrl: "about.html"
            
        );

【讨论】:

以上是关于使用 AngularJS 路由时有没有办法预加载模板?的主要内容,如果未能解决你的问题,请参考以下文章

Angularjs2 - 在应用程序启动之前预加载服务器配置[重复]

AngularJS:如何在页面完全加载之前显示预加载或加载?

加载 angularjs 视图后加载 jquery 模块?

ASP.net MVC 5 路由:加载基本 url 时出现 ajax 错误,但在最后添加 home/Index 时有效

预加载脚本文件

vue加载组件报错说提前加载