【问题标题】:Loading relative templateUrl加载相关 templateUrl
【发布时间】:2014-05-14 20:23:09
【问题描述】:

我一直在努力寻找创建模块化、可扩展的 Angular 应用程序的最佳方式。我真的很喜欢angular-boilerplateangular-app 等项目的结构,其中所有相关文件都按部分和指令的功能分组在一起。

project
|-- partial
|   |-- partial.js
|   |-- partial.html
|   |-- partial.css
|   |-- partial.spec.js

但是,在所有这些示例中,模板 URL 是相对于基本 url 加载的,而不是相对于当前文件:

angular.module('account', [])
.config(function($stateProvider) {
  $stateProvider.state('account', {
    url: '/account',
    templateUrl: 'main/account/account.tpl.html', // this is not very modular
    controller: 'AccountCtrl',
  });
})

这不是非常模块化的,在大型项目中可能会变得难以维护。每次移动这些模块时,我都需要记住更改templateUrl 路径。如果有某种方法可以加载相对于当前文件的模板,例如:

templateUrl: './account.tpl.html'

有没有什么方法可以在角度上做这样的事情?

【问题讨论】:

标签: angularjs angularjs-directive angular-ui-router angular-template


【解决方案1】:

现在最好的方法是使用模块加载器,如 browserify、webpack 或 typescript。还有很多其他的。由于可以从文件的相对位置生成要求,并且能够通过转换或像 partialify 这样的加载器导入模板的额外好处,您甚至不必再使用模板 url。只需通过 require 内联模板即可。

我的旧答案在下面仍然可用:

我写了一篇关于这个主题的帖子,并在我们当地的 Angular 聚会上发表了讲话。我们大多数人现在都在生产中使用它。

只要您的文件结构在您的模块中有效地表示,这非常简单。这是解决方案的快速预览。全文链接如下。

var module = angular.module('myApp.things', []);

var all = angular.module('myApp.things.all', [
    'myApp.things',
    'things.someThing',
    'things.someOtherThing',
    'things.someOtherOtherThing',
]);

module.paths = {
    root: '/path/to/this/thing/',
    partials: '/path/to/this/thing/partials/',
    sub: '/path/to/this/thing/sub/',
};

module.constant('THINGS_ROOT', module.paths.root);
module.constant('THINGS_PARTIALS', module.paths.partials);
module.constant('THINGS_SUB', module.paths.sub);

module.config(function(stateHelperProvider, THINGS_PARTIALS) {

    stateHelperProvider.setNestedState({
        name: 'things',
        url: '/things',
        templateUrl: THINGS_PARTIALS + 'things.html',
    });
});

然后任何子模块或“相对”模块看起来像这样:

var module = angular.module('things.someThing', ['myApp.things']);
var parent = angular.module('myApp.things');

module.paths = {
    root: parent.paths.sub + '/someThing/',
    sub: parent.paths.sub + '/someThing/sub/',
    partials: parent.paths.sub + '/someThing/module/partials/',
};

module.constant('SOMETHING_ROOT', module.paths.root);
module.constant('SOMETHING_PARTIALS', module.paths.partials);
module.constant('SOMETHING_SUB', module.paths.sub);

module.config(function(stateHelperProvider, SOMETHING_PARTIALS) {

    stateHelperProvider.setNestedState({
        name: 'things.someThing',
        url: "/someThing",
        templateUrl: SOMETHING_PARTIALS + 'someThing.html',
    });
});

希望这会有所帮助!

全文:Relative AngularJS Modules

干杯!

【讨论】:

  • 这是一个非常优雅的解决方案。迫不及待开始使用它!
  • 这看起来很有趣。我对它的主要关注是这会增加对父模块的依赖,以及潜在的循环依赖。让父模块依赖子模块通常不是更好的做法吗?你还能单独测试模块“things.someThing”吗?
  • 这个用例不是关于依赖注入,而是更多的文件结构。它主要适用于可能存在于其他模块内部的模块,以便组织或构建一个平台以供 3rd 方集成和模块正确构建并位于您的文件结构中。
  • 因为我们在这里使用注入,也许值得为路径设置另一个集中单元(或模块),这样我们就会有很多常量定义为 Home.Second.Third 等。
【解决方案2】:

我认为您最终会发现维护相对于 js 文件的路径会更加困难,如果可能的话。交付时,您很可能希望将所有 javascript 文件连接到一个文件,在这种情况下,您将希望模板与 baseUrl 相关。此外,如果您通过 ajax 获取模板,除非您将它们预先打包在 $templateCache 中,否则 Angular 默认会这样做,您肯定会希望它们相对于 baseUrl,因此服务器知道在您的 js 后在哪里可以找到它们文件已经发送到浏览器。

也许您不喜欢在开发中使用它们相对于 baseUrl 的原因是因为您没有在本地运行服务器?如果是这样,我会改变它。这将使您的生活更轻松,特别是如果您要使用路线。我会查看Grunt,它有一个非常简单的服务器,您可以在本地运行它来模拟名为Grunt Connect 的生产设置。您还可以查看像 Yeoman 这样的项目,它提供了使用 Grunt 的预打包前端开发环境,因此您不必花费大量时间进行设置。 Angular Seed 项目也是用于本地开发的 Grunt 设置的一个很好的例子。

【讨论】:

  • 是的,我猜 Angular 并没有真正为此设置。我只是不喜欢有一个相对的 baseUrl,因为在上面的项目结构中,模板/指令模板/部分对总是在同一个目录中。我想我需要使用 RequireJS 或 Browserify 之类的东西来获得这种功能。
  • 我通常将模板文件的路径放在一个常量中。类似于... angular.constant('TPL_PATH', '/main/templates/') 我为每个模块提供了自己的模板路径和相同名称的常量。这样我所有的指令都只是...... templateUrl: TPL_PATH + 'name.tpl.html' 但每个模块的 TPL_PATH 仍然不同
  • 有趣。这绝对是对另一种方式的改进。另一种选择是通过使用
  • 我看到的问题是,在我试图理解这一点时,当我将我的功能从应用程序转移到应用程序时,我必须记住不仅要转移脚本区域部分,还要转移到任何地方存储所有模板。我没有移动一个目录,而是移动了两个目录。或者也许我没有正确理解这一点。
  • 当您将两个目录放在一个共享的父目录中时,它们会合二为一。您应该将模板和脚本视为同一件事。它们结合起来就是您的应用程序的源代码。如果没有其中一个,您的应用程序将无法运行
【解决方案3】:

我一直在研究这个问题。我使用 gulp 打包我的生产模板,但我一直在努力寻找一个我对开发感到满意的解决方案。

这就是我结束的地方。下面的 sn-p 允许按照您认为合适的方式重新连接任何 url。

angular.module('rm').config(function($httpProvider) {

  //this map can be defined however you like
  //one option is to loop through script tags and create it automatically
  var templateMap = {
    "relative.tpl.html":"/full/path/to/relative.tpl.html",
    etc...
  };

  //register an http interceptor to transform your template urls
  $httpProvider.interceptors.push(function () {
    return {
      'request': function (config) {
        var url = config.url;
        config.url = templateMap[url] || url;
        return config;
      }
    };
  });
});

【讨论】:

    【解决方案4】:

    目前可以使用systemJs 模块加载器来做你想做的事情。

    import usersTemplate from './users.tpl';
    
    var directive = {
       templateUrl: usersTemplate.name
    }
    

    你可以在这里查看好例子https://github.com/swimlane-contrib/angular1-systemjs-seed

    【讨论】:

      【解决方案5】:

      我一直在使用templateUrl: './templateFile.tpl.html,但更新了一些东西,它坏了。所以我把它扔在那里。

      我一直在我的 Gruntfile.js html2js 对象中使用它:

      html2js: {
        /**
         * These are the templates from `src/app`.
         */
        app: {
          options: {
            base: '<%= conf.app %>',
            rename: function( templateName ) {
              return templateName.substr( templateName.lastIndexOf('/') );
            }
          },
          src: [ '<%= conf.app %>/**/{,*/}<%= conf.templatePattern %>' ],
          dest: '.tmp/templates/templates-app.js'
        }
      }
      

      我知道这会导致冲突,但这对我来说是一个比每次都在每个文件中编辑/path/to/modules/widgets/wigdetName/widgetTemplate.tpl.html 时更小的问题,我将它包含在另一个项目中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-12
        • 1970-01-01
        • 1970-01-01
        • 2019-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-11
        相关资源
        最近更新 更多