[英]Angular directive templateUrl relative to .js file
我正在建立一個角度指令,將在幾個不同的位置使用。 我不能總是保證使用該指令的應用程序的文件結構,但我可以強制用戶將directive.js
和directive.html
(不是真正的文件名)放在同一個文件夾中。
當頁面評估directive.js
,它認為templateUrl
是相對於它自己的。 是否可以將templateUrl
設置為相對於directive.js
文件?
或者建議只在模板中包含模板。
我想我可能想根據不同的情況加載不同的模板,所以寧願能夠使用相對路徑而不是更新directive.js
當前正在執行的腳本文件將始終是scripts數組中的最后一個,因此您可以輕松找到其路徑:
// 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);
我的測試基於以下關於使用require來延遲加載角度的博客: http : //ify.io/lazy-loading-in-angularjs/
require.js會產生一個requireConfig引導程序
requireConfig會產生一個有角度的app.js
angular app.js會產生我的routes.js
我有一個由revel web框架和asp.net mvc提供的相同代碼。 在revel document.getElementsByTagName(“script”)中生成了一個指向我的require bootstrap js文件而不是我的routes.js的路徑。 在ASP.NET MVC中,它生成了Visual Studio注入的Browser Link腳本元素的路徑,該腳本元素在調試會話期間放在那里。
這是我的工作路線.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/
我做的另一個好處是利用require配置並在其中放置一些自定義配置。 即添加
customConfig: { baseRouteUrl: '/AngularLazyBaseLine/Home/Content' }
然后,您可以使用routes.js內部的以下代碼來獲取它
var requireConfig = requirejs.s.contexts._.config;
console.log('requireConfig.customConfig.baseRouteUrl:' + requireConfig.customConfig.baseRouteUrl);
有時您需要預先定義baseurl,有時您需要動態生成它。 您的情況選擇。
除了Alon Gubkin的答案之外,我建議使用Immediately-Invoked Function Expression定義一個常量來存儲腳本的路徑並將其注入到指令中:
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'
}
});
有些人可能會認為它有點“hacky”,但我認為只有一種方法可以做到這一點,任何東西都會變成黑客。
我也有很多運氣也這樣做:
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;
}
});
然后在應用程序中包含模塊后在應用程序中使用代碼。
在app配置功能中:
.config(['$routeProvider', '$appUrlProvider', function ($routeProvider, $appUrlProvider) {
$routeProvider
.when('/path:folder_path*', {
controller: 'BrowseFolderCntrl',
templateUrl: $appUrlProvider.route('views/browse-folder.html')
});
}]);
在app控制器中(如果需要):
var MyCntrl = function ($scope, $appUrl) {
$scope.templateUrl = $appUrl('views/my-angular-view.html');
};
它會創建一個新的javascript錯誤並拉出堆棧跟蹤。 然后解析出所有URL(不包括調用行/ char號)。
然后,您可以拉出數組中的第一個,該數組將是運行代碼的當前文件。
如果你想集中代碼然后拉出數組中的第二個( [1]
)來獲取調用文件位置,這也很有用。
正如一些用戶指出的那樣,相關路徑在構建靜態文件時沒有用處,我強烈建議這樣做。
Angular中有一個名為$ templateCache的漂亮功能,它或多或少地緩存模板文件,下次該角度需要一個,而不是發出實際請求,它提供緩存版本。 這是使用它的典型方法:
module = angular.module('myModule');
module.run(['$templateCache', function($templateCache) {
$templateCache.put('as/specified/in/templateurl/file.html',
'<div>blabla</div>');
}]);
})();
因此,通過這種方式,您既可以解決相對網址的問題,也可以獲得性能。
當然我們喜歡使用單獨的模板html文件(與反應相反)的想法,所以上面的內容並不好。 這是構建系統,它可以讀取所有模板html文件並構造如上所述的js。
grunt,gulp,webpack有幾個html2js模塊,這是它們背后的主要思想。 我個人經常使用gulp ,所以我特別喜歡gulp-ng-html2js,因為它非常容易。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.