angular模板加載 ----ng-template


Angularjs作為mvc(或者說mvvm)框架,同樣具備模板這一基本概念。

NG加載模板的順序為 內存加載---AJAX加載。

如果排版亂掉,請查閱https://www.zybuluo.com/bornkiller/note/6023

內存加載

如果之前使用過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服務put方法負責向內存寫入模板內容。

  • 通過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標簽絕對不會發出HTTP請求,具體討論見最后。
實際應用模板時候,使用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 的相關內容,將作為單獨篇章出現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM