Angular指令templateUrl相对于.js文件
我正在构build一个angular度指令,将在几个不同的位置使用。 我不能总是保证指令的应用程序的文件结构,但我可以强制用户把directive.js和directive.html (不是真正的文件名)放在同一个文件夹中。 
 当页面评估directive.js ,它认为templateUrl是相对于它自己的。 有没有可能将templateUrl设置为相对于directive.js文件? 
还是build议只在指令本身包含模板。
 我想我可能要根据不同的情况加载不同的模板,所以宁愿能够使用相对path,而不是更新directive.js 
当前正在执行的脚本文件将始终是脚本数组中的最后一个,因此您可以轻松find它的path:
 // directive.js var scripts = document.getElementsByTagName("script") var currentScriptPath = scripts[scripts.length-1].src; angular.module('app', []) .directive('test', function () { return { templateUrl: currentScriptPath.replace('directive.js', 'directive.html') }; }); 
如果您不确定脚本名称是什么(例如,如果您将多个脚本打包成一个脚本),请使用以下命令:
 return { templateUrl: currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1) + 'directive.html' }; 
注意 :在使用闭包的情况下,您的代码应该在外面以确保在正确的时间对currentScript进行评估,例如:
 // directive.js (function(currentScriptPath){ angular.module('app', []) .directive('test', function () { return { templateUrl: currentScriptPath.replace('directive.js', 'directive.html') }; }); })( (function () { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length - 1].src; return currentScriptPath; })() ); 
正如你所说的,你想在不同的时间提供不同的模板到指令,为什么不允许模板本身作为一个属性传递给指令?
 <div my-directive my-template="template"></div> 
 然后在指令中使用类似$compile(template)(scope)东西。 
该代码位于一个名为routes.js的文件中
以下对我不起作用:
 var scripts = document.getElementsByTagName("script") var currentScriptPath = scripts[scripts.length-1].src; var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); 
下面做了:
 var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); 
我的testing是基于以下关于使用require来延迟加载angular度的博客: http : //ify.io/lazy-loading-in-angularjs/
require.js生成一个requireConfig引导程序
requireConfig生成一个angular度的app.js
angular度app.js会导致我的routes.js
我有相同的代码正在由一个狂欢网页框架和asp.net mvc服务。 在revel document.getElementsByTagName(“脚本”)产生了一个path,我需要引导js文件,而不是我的routes.js。 在ASP.NET MVC中,它产生了一个到Visual Studio注入的Browser Link脚本元素的path,该元素在debugging会话期间放在那里。
这是我的工作routes.js代码:
 define([], function() { var scripts = document.getElementsByTagName("script"); var currentScriptPath = scripts[scripts.length-1].src; console.log("currentScriptPath:"+currentScriptPath); var baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); var bu2 = document.querySelector("script[src$='routes.js']"); currentScriptPath = bu2.src; console.log("bu2:"+bu2); console.log("src:"+bu2.src); baseUrl = currentScriptPath.substring(0, currentScriptPath.lastIndexOf('/') + 1); console.log("baseUrl:"+baseUrl); return { defaultRoutePath: '/', routes: { '/': { templateUrl: baseUrl + 'views/home.html', dependencies: [ 'controllers/HomeViewController', 'directives/app-style' ] }, '/about/:person': { templateUrl: baseUrl + 'views/about.html', dependencies: [ 'controllers/AboutViewController', 'directives/app-color' ] }, '/contact': { templateUrl: baseUrl + 'views/contact.html', dependencies: [ 'controllers/ContactViewController', 'directives/app-color', 'directives/app-style' ] } } }; }); 
这是从Revel运行时的控制台输出。
 currentScriptPath:http://localhost:9000/public/ngApps/1/requireBootstrap.js routes.js:8 baseUrl:http://localhost:9000/public/ngApps/1/ routes.js:10 bu2:[object HTMLScriptElement] routes.js:13 src:http://localhost:9000/public/ngApps/1/routes.js routes.js:14 baseUrl:http://localhost:9000/public/ngApps/1/ 
我所做的另一件好事是利用requireconfiguration,并在其中添加一些自定义configuration。 即添加
 customConfig: { baseRouteUrl: '/AngularLazyBaseLine/Home/Content' } 
你可以通过在routes.js中使用下面的代码来获得它
 var requireConfig = requirejs.s.contexts._.config; console.log('requireConfig.customConfig.baseRouteUrl:' + requireConfig.customConfig.baseRouteUrl); 
有时你需要预先定义一个baseurl,有时你需要dynamic生成它。 你的select你的情况。
除了来自Alon Gubkin的回答之外,我build议使用立即调用的函数expression式来定义一个常量来存储脚本的path并将其注入到指令中:
 angular.module('app', []) .constant('SCRIPT_URL', (function () { var scripts = document.getElementsByTagName("script"); var scriptPath = scripts[scripts.length - 1].src; return scriptPath.substring(0, scriptPath.lastIndexOf('/') + 1) })()) .directive('test', function(SCRIPT_URL) { return { restrict : 'A', templateUrl : SCRIPT_URL + 'directive.html' } }); 
 有些人可能会认为它有点“哈克”,但我认为,直到只有一种方法可以做到这一点,任何事情都会变得怪异。 
 我也有这样做的运气很多: 
 angular.module('ui.bootstrap', []) .provider('$appUrl', function(){ this.route = function(url){ var stack = new Error('dummy').stack.match(new RegExp(/(http(s)*\:\/\/)[^\:]+/igm)); var app_path = stack[1]; app_path = app_path.slice(0, app_path.lastIndexOf('App/') + 'App/'.length); return app_path + url; } this.$get = function(){ return this.route; } }); 
 然后,在应用程序中包含模块后,在应用程序中使用代码。 
 在一个应用程序configurationfunction: 
 .config(['$routeProvider', '$appUrlProvider', function ($routeProvider, $appUrlProvider) { $routeProvider .when('/path:folder_path*', { controller: 'BrowseFolderCntrl', templateUrl: $appUrlProvider.route('views/browse-folder.html') }); }]); 
并在应用程序控制器(如果需要):
 var MyCntrl = function ($scope, $appUrl) { $scope.templateUrl = $appUrl('views/my-angular-view.html'); }; 
 它创build一个新的JavaScript错误,并拉出堆栈跟踪。 然后parsing出所有的URL(不包括调用行/字符编号)。 
 然后,您可以将数组中的第一个作为代码正在运行的当前文件。 
 如果你想集中代码,然后在数组中取出第二个( [1] )来获取调用文件的位置 
正如几位用户指出的那样,build立静态文件时相关的path是没有帮助的,我强烈推荐这样做。
在Angular中有一个非常漂亮的function叫做$ templateCache ,它或多或less地caching了模板文件,下一次这个angular度需要一个,而不是提供一个实际的请求来提供caching的版本。 这是一个典型的使用方法:
 module = angular.module('myModule'); module.run(['$templateCache', function($templateCache) { $templateCache.put('as/specified/in/templateurl/file.html', '<div>blabla</div>'); }]); })(); 
所以这样你们就可以解决相关网站的问题,并且在性能上获得成功。
当然,我们喜欢有独立的模板html文件(与反应相反)的想法,所以上述是不好的。 这里是构build系统,它可以读取所有模板html文件,并构build如上所述的js。
grunt,gulp,webpack有几个html2js模块,这是他们背后的主要思想。 我个人使用gulp ,所以我特别喜欢gulp-ng-html2js,因为它非常简单。