42

我一直在努力寻找创建模块化、可扩展的角度应用程序的最佳方法。我真的很喜欢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'

有没有办法在角度做这样的事情?

4

5 回答 5

17

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

我的旧答案仍然可以在下面找到:

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

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

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',
    });
});

希望这可以帮助!

全文:相对 AngularJS 模块

干杯!

于 2014-11-12T18:47:45.563 回答
16

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

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

于 2014-04-03T07:59:29.177 回答
1

我一直在咀嚼这个问题有一段时间了。我使用 gulp 来打包我的模板以用于生产,但我一直在努力寻找一个我对开发感到满意的解决方案。

这就是我结束的地方。下面的代码片段允许根据您认为合适的方式重新连接任何 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;
      }
    };
  });
});
于 2015-03-23T10:11:26.503 回答
1

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

import usersTemplate from './users.tpl';

var directive = {
   templateUrl: usersTemplate.name
}

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

于 2016-05-17T11:24:40.537 回答
-1

我一直在使用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每次都在每个文件中进行编辑的小问题,我将它包含在另一个项目中。

于 2015-03-24T21:26:14.220 回答