angular模板載入 ----ng-template
Angularjs作為mvc(或者說mvvm)框架,同樣具備模板這一基本概念。
NG載入模板的順序為 記憶體載入---AJAX載入。
記憶體載入
如果之前使用過Bootstrap 外掛的ng版,即angular-ui,就會了解到這種方式的具體應用。模板本質上是字串,把字串直接寫入記憶體,載入時直接從記憶體獲取,速度會更快,有兩種方式顯式啟用記憶體載入。
- 通過使用
$templateCache
service來實現
angular.module('myApp', [])
.controller('myCtrl', ['$scope','$templateCache', function ($scope,$templateCache){
var tmp = '<h4>lovestory</h4>'
+ '<p>這是直接呼叫$templateCache服務獲取模板檔案的方式</p>'
+ '<a href="http://www.baidu.com">服務啟用templateCache方式</a>';
$templateCache.put('lovestory.html',tmp);
}])
$templateCache
- 通過
script
標籤引入
<script type="text/ng-template" id="lovestory.html">
<h4>lovestory</h4>
<p>這是script標籤獲取模板檔案的方式</p>
<a href="http://www.baidu.com">標籤啟用templateCache方式</a>
</script>
這裡需要注意,type="text/ng-template"
是指明這是ng模板,id屬性是指實際使用模板時的一個引用,標籤之間的內容才是實際的模板內容。而且,需要注意,id絕對不是URL,這個script
實際應用模板時候,使用
ID
屬性,即可從記憶體中獲取對應資料。
<div ng-include="'lovestory.html'" class="well"></div>
使用ng-include
的時候,應該注意,id相當於一個字串,不是ng-expression
,所以不要忘了加單引號。
AJAX載入
上述的記憶體載入,相當於一個預定義模板,定義在client-side
,不會與伺服器有任何互動,適合變化頻率低的模板。
當NG在記憶體中找不到對應模板時,就會啟用AJAX請求,去拉取對應模板。假設專案入口檔案地址為http://127.0.0.1/index.html;
<div ng-include="'lovestory.html'" class="well"></div>
在指令中同樣可以使用,templateUrl對應值
angular.module('myApp', [])
.directive('templateDemo', ['$log', function($log){
return {
restrict: 'A', // E = Element, A = Attribute, C = Class, M = Comment
templateUrl: 'butterfly.html',
replace: true,
link: function($scope, iElm, iAttrs, controller) {}
}
}])
記憶體中沒有對應模板時,AJAX請求地址為http://127.0.0.1/lovestory.html, 請求成功後將對應內容寫入$templateCache
,在頁面不進行重新整理,不手動刪除的情況下,寫入的內容不會丟失。而且,務必記住,AJAX是有快取控制的。。。
記憶體模板優點
在雅虎前端優化34條裡,有一條是“合併壓縮檔案”。
合併壓縮檔案可以減小HTTP請求量,又可以減小網路傳輸量,對於路徑依賴並不嚴重的JS,CSS檔案完全是必備,因為各JS,CSS檔案開發時分割為不同的檔案,實現各自的功能需求,上線時合併即可,但是,HTML檔案可以壓縮,但是無法合併,因為路徑依賴嚴重。
以我為學習Angularjs而做的個人部落格練習 路由為例:
angular.module('administratorApp',[])
.config(function ($routeProvider,$locationProvider) {
$locationProvider.html5Mode(false);
$routeProvider
.when('/manage', {
templateUrl: 'views/manage.html',
controller: 'ManageCtrl'
})
.when('/diary/:key', {
templateUrl: 'views/diaryDetail.html',
controller: 'DiaryDetailCtrl',
})
.when('/diary', {
templateUrl: 'views/diaryList.html',
controller: 'DiaryListCtrl'
})
.when('/publish/:key', {
templateUrl: 'views/update.html',
controller: 'UpdateCtrl'
})
.when('/publish', {
templateUrl: 'views/publish.html',
controller: 'PublishCtrl'
})
.when('/record', {
templateUrl: 'views/record.html',
controller: 'RecordCtrl'
})
.otherwise({
redirectTo: '/diary'
});
});
六個控制器需要六個模板,六次HTTP請求載入資料量並不大的模板資源浪費嚴重。NG的優化方案是,通過虛擬路徑取代實體路徑,去除掉server-side
的路徑依賴。
好處就是,一個JS檔案一次HTTP請求,而不是六次。壞處就是記憶體壓力變大,PC上無所謂,開發web app(mobile)就需要注意幾點。
- 移動端記憶體太脆,儘量不要使用上述所說的預定義模板,因為模板會全部載入到記憶體中
- AJAX請求完畢,會自動把結果放入cache裡,所以需要手動控制.模板與控制器存在對應關係,可以在控制器內部加上如下程式碼
$scope.$on('$locationChangeStart',function(){
$templateCache.remove('****.html');
})
- $routeProvider的
template
,templateUrl
可以是函式,通過函式返回值可以控制模板載入。- PS::本人並未涉及到移動端開發,所以此處為思考所得,而且隨著手機硬體效能提升,記憶體不再是個困擾。
$templateCache 方法
$templateCache
基於cacheFactory
而來,介面保持一致,可以認為
\$templateCache = \$cacheFactory('template');
方法 | 功能 |
---|---|
put | 向記憶體寫入模板內容 |
get | 從記憶體獲取模板內容 |
remove | 傳入key值,刪除對應模板內容 |
removeAll | 刪除所有模板內容 |
destroy | 解除key-value對應關係,但不釋放記憶體 |
info | 模板快取物件的資訊 |
Grunt與ID屬性誤解
module.exports = function(grunt){
grunt.initConfig({
html2js : {
simple : {
options : {
base : '',
module : 'templateStore'
},
files : [{
src : ['views/*.html'],
dest : 'build/scripts/templateStore.js'
}]
}
}
});
grunt.loadNpmTasks('grunt-html2js');
grunt.registerTask('default',['html2js']);
}
這是我目前使用Grunt--html2js的配置方案,目的是將views
資料夾下的所有模板檔案全部放入templateStore
模組中,各模板對應ID即為路徑,生成的部分程式碼如下:
angular.module("views/diaryList.html", []).run(["$templateCache", function($templateCache) {
$templateCache.put("views/diaryList.html", '*******'
}]);
這部分程式碼等效於
<script type="text/ng-template" id="views/diaryList.html">
***********
</script>
現在應該明白,id只是個標示,不是URL。。。。。。
AJAX快取
涉及到部分HTTP Header 和 XHR2 的相關內容,將作為單獨篇章出現。