參考地址:https://github.com/kittencup/angular2-ama-cn/issues/18
前言:
templateUrl表示的是組件在瀏覽器中運行時依賴的模板地址,所以在templateUrl這里並不能填寫./xxx.html這種路徑,你要從瀏覽器的路徑考慮它
src
index.html
index.js // 可能是打包后生成的
components
button
button.ts
button.html
當你打開index.html時你想一下,加載button.html的路徑是什么,/components/button/button.html
所以對於你的button.ts里的templateUrl 應該寫成 /components/button/button.html
由此可見,templateUrl的路徑應該是根據你執行的html文件路徑來計算
問題
如果每個component文件夾內組件的templateUrl都需要寫上/components是不是很麻煩,當然在這里路徑還是比較短而簡單的,如果路徑很長呢/a/b/c/d/e/f/components 那么你是不是在每個組件內都要寫上那么長的地址,而且后期修改起來也要每個文件都改一下。
解決方案
Angular 2 幫你想到了這個問題,可使用 package:或者asset: 占位符,這2個占位符默認對應的值是/packages,當你設置templateUrl:'package:/button/button.html',在運行時這個地址會被替換為/packages/button/button.html,在這里我們需要修改一下默認的占位符地址,通過重設Token為PACKAGE_ROOT_URL的provide
import {provide,PACKAGE_ROOT_URL} from 'angular2/core';
bootstrap(App,[provide(PACKAGE_ROOT_URL,{useValue: '/components'})])
這樣在運行時編譯出得地址就變為 /components/button/button.html
更復雜的問題
package:或者asset: 占位符可以解決開發時運行時加載的路徑,當項目發布到正式環境后,我們的靜態文件應該會在CDN上,當然通過PACKAGE_ROOT_URL也是能解決這個路徑問題,但是不夠靈活,如果我想templateUrl從http://cdn.template.kittencup.com加載,而styleUrl到http://cdn.style.kittencup.com加載,那么單單用一個PACKAGE_ROOT_URL是無法解決的
解決方案
在Angular 2源碼中無論templateUrl和styleUrl在加載前都會通過UrlResolver對象來進行處理,UrlResolver對象是通過依賴注入獲取的,源碼在 src/compiler/url_resolver.ts ,默認的UrlResolver是根據PACKAGE_ROOT_URL的值來替換package:或者asset: 占位符,所以我們可以重設UrlResolver,代碼如下
一、
@Component({ selector: "hz-stepbody", templateUrl: "dm_template.html"//注意,這里不能用/dm_template.html }) class Stepbody { }
import {UrlResolver} from 'angular2/compiler';
class MyUrlResolver extends UrlResolver {
resolve(baseUrl: string, url: string): string {
if (url.substr(-4) === '.css') {
return super.resolve('http://cdn.style.kittencup.com', url);
}else if(url.substr(-5) === '.html'){
return super.resolve('http://cdn.template.kittencup.com', url);
}
return super.resolve(baseUrl, url);
}
}
bootstrap(App, [provide(UrlResolver, {useClass: MyUrlResolver})]);
二、
@Component({ selector: "hz-stepbody", templateUrl: "mytemplate:dm_template.html" }) class Stepbody { }
import {provide, PACKAGE_ROOT_URL} from 'angular2/core';
import {UrlResolver} from 'angular2/compiler';
class MyUrlResolver extends UrlResolver {
resolve(baseUrl: string, url: string): string {
var resolvedUrl = url;
if (url.substr(0, 6) == "mytemplate") {
resolvedUrl = resolvedUrl.replace("mytemplate:", "/template/gz/");
}else {
resolvedUrl = super.resolve(baseUrl, url);
}
return resolvedUrl;
}
}
