国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
AngularJS進(jìn)階(二十五)requirejs + angular + angular

requirejs + angular + angular-route 淺談HTML5單頁(yè)面架構(gòu)

      眾所周知,現(xiàn)在移動(dòng)Webapp越來(lái)越多,例如天貓、京東、國(guó)美這些都是很好的例子。而在Webapp中,又要數(shù)單頁(yè)面架構(gòu)體驗(yàn)最好,更像原生app。簡(jiǎn)單來(lái)說(shuō),單頁(yè)面App不需要頻繁切換網(wǎng)頁(yè),可以局部刷新,整個(gè)加載流暢度會(huì)好很多。

      廢話就不多說(shuō)了,直接到正題吧,淺談一下我自己理解的幾種單頁(yè)面架構(gòu): 

      1、requirejs+angular+angular-route(+zepto)

      最后這個(gè)zepto可有可無(wú),主要是給團(tuán)隊(duì)中實(shí)在用不爽angular的同學(xué),可以靈活修改一下頁(yè)面某些內(nèi)容。當(dāng)然,嚴(yán)謹(jǐn)?shù)捻?xiàng)目不應(yīng)該出現(xiàn)zepto。 

      2、requirejs+backbone+zepto+template 

      這個(gè)方案更靈活,MVC味道更濃,使用自定義的template模版庫(kù) 

      3、requirejs+route+template 

      這個(gè)方案最靈活,看破紅塵,針對(duì)簡(jiǎn)單的業(yè)務(wù)用最簡(jiǎn)單的方式,只需要路由和模版,不用MVC框架 

      4、react 

     個(gè)人感覺(jué),react更偏向于view層的組件,更native,但實(shí)施難度略高

     說(shuō)到項(xiàng)目架構(gòu),往往要考慮很多方面:

      方便:例如使用jquery,必然比沒(méi)有使用jquery方便很多,所以大部分網(wǎng)站都接入類似的庫(kù);

     性能優(yōu)化:包括加載速度、渲染效率;

     代碼管理:大型項(xiàng)目需要考慮代碼的模塊化,模塊間低耦合高內(nèi)聚,目的就為了團(tuán)隊(duì)合作效率;

     可擴(kuò)展性:這個(gè)不用說(shuō)了。

     學(xué)習(xí)成本:一個(gè)框架再好,團(tuán)隊(duì)新成員難以掌握,學(xué)習(xí)難度大,結(jié)果很容易造成代碼混亂。

      而根據(jù)實(shí)際經(jīng)驗(yàn)來(lái)看,方便是必然首要地位,除此之外,應(yīng)該是代碼管理了。團(tuán)隊(duì)合作過(guò)程中,各種協(xié)作,代碼沖突等等,都會(huì)給一個(gè)優(yōu)秀框架帶來(lái)各種奇怪難題。所以,有好的框架還不夠,我們還需要根據(jù)自身業(yè)務(wù)和團(tuán)隊(duì)的情況,按需裁剪或者修改框架,找到最佳的實(shí)施方案。

      接下來(lái),將分三個(gè)隨筆分別介紹一下我心目中前三種架構(gòu)的較好實(shí)施方案,而最后一種,跟前三種有種道不同不相為謀的感覺(jué),加上自己道行不夠,還是暫且不提了。

      這一篇,先說(shuō)說(shuō)第一種:requirejs+angular+angular-route

      移動(dòng)端單頁(yè)面Web相對(duì)多頁(yè)面來(lái)說(shuō),模塊化管理顯得非常重要,因?yàn)槿绻麤](méi)有模塊化,頁(yè)面初始化時(shí)就把所有的js和所有模版都加載進(jìn)來(lái),會(huì)導(dǎo)致首屏速度極慢。這一點(diǎn),大家都理解的。 

      所以,requirejs或者類似的模塊化框架是必不可少的。requirejs比較流行,配合grunt可以做好整套的自動(dòng)化工具,我們就以這個(gè)為例子吧。

     首先,來(lái)看看demo項(xiàng)目的整體架構(gòu)。

     除了類庫(kù)外,業(yè)務(wù)代碼都以模塊劃分目錄,這樣做便于實(shí)際開(kāi)發(fā)中,按模塊化合并js和html,也利于多人并行開(kāi)發(fā),各自修改不同的模塊,互不影響。

     另外,說(shuō)說(shuō)三個(gè)重點(diǎn)的根目錄文件:

      index.html,這個(gè)就是單頁(yè)面唯一一個(gè)html了,其他都只是片段模版(tpl.html)。一般可以把這個(gè)html放到動(dòng)態(tài)服務(wù)器上,保持零緩存,同時(shí)這里可以攜帶各種js版本控制信息和必要的用戶數(shù)據(jù)。

      main.js,這個(gè)是由requirejs引入的第一個(gè)業(yè)務(wù)js,主要是配置requirejs;

      router.js,這個(gè)是整個(gè)網(wǎng)站/app的路由配置,在實(shí)際部署中,可以把main.js和router.js合并。

第一步,先看看index.html需要做什么變化

  1. <!DOCTYPE html>  
  2. <html>  
  3. <head lang="en">  
  4.     <meta charset="UTF-8">  
  5.     <title>Angular & Requirejs</title>  
  6. </head>  
  7. <body>  
  8. <div id="container" ng-view></div>  
  9. <script data-baseurl="./" data-main="main.js" src="libs/require.js" id="main"></script>  
  10. </body>  
  11. </html>  

      相對(duì)angular的寫(xiě)法,這里由于使用requirejs管理全部模塊,所以index.html中不需要引入angular等,只是設(shè)置了一個(gè)帶ng-view屬性的div,用于充當(dāng)整個(gè)App的視圖區(qū)域。 

      data-baseurl是額外加入的屬性,主要好處是可以輕松在html(0緩存)中對(duì)js的url進(jìn)行修改。 

      data-main就是requirejs的標(biāo)準(zhǔn)寫(xiě)法了,跳過(guò)不說(shuō)。

第二步,main.js,也就是requirejs的配置

[javascript] view plain copy
print?
  1. 'use strict';  
  2. (function (win) {  
  3.     //配置baseUrl  
  4.     var baseUrl = document.getElementById('main').getAttribute('data-baseurl');  
  5.     /* 
  6.      * 文件依賴 
  7.      */  
  8.     var config = {  
  9.         baseUrl: baseUrl,             // 依賴相對(duì)路徑  
  10.         paths: {                    // 如果某個(gè)前綴的依賴不是按照baseUrl拼接這么簡(jiǎn)單,就需要在這里指出  
  11.             underscore: 'libs/underscore',  
  12.             angular: 'libs/angular',  
  13.             'angular-route': 'libs/angular-route',  
  14.             text: 'libs/text'             // 用于requirejs導(dǎo)入html類型的依賴  
  15.         },  
  16.         shim: { //引入沒(méi)有使用requirejs模塊寫(xiě)法的類庫(kù)。例如underscore這個(gè)類庫(kù),本來(lái)會(huì)有一個(gè)全局變量'_'。這里shim等于快速定義一個(gè)模塊,把原來(lái)的全局變量'_'封裝在局部,并導(dǎo)出為一個(gè)exports,變成跟普通requirejs模塊一樣  
  17.             underscore: {  
  18.                 exports: '_'  
  19.             },  
  20.             angular: {  
  21.                 exports: 'angular'  
  22.             },  
  23.             'angular-route': {  
  24.                 deps: ['angular'],   //依賴什么模塊  
  25.                 exports: 'ngRouteModule'  
  26.             }  
  27.         }  
  28.     };  
  29.     require.config(config);  
  30.     require(['angular', 'router'], function(angular){  
  31.         angular.bootstrap(document, ['webapp']);  
  32.     });  
  33. })(window);  

      requirejs的語(yǔ)法,說(shuō)來(lái)話長(zhǎng),簡(jiǎn)單在代碼中做了注釋。有興趣了解詳情的可以參考官網(wǎng):http://requirejs.org/;

      angular可以參考:https://docs.angularjs.org/guide/filter

      這里配置好requirejs后,就做第一步工作,引入angular和angular的路由配置,然后用angular.bootstrap(document, [‘webapp’]); 手工啟動(dòng)angular,這里webapp是router.js中定義的angular module。

第三步,配置這個(gè)router

[javascript] view plain copy
print?
  1. define(['angular', 'require', 'angular-route'], function (angular, require) {  
  2.     var app = angular.module('webapp', ['ngRoute']);  
  3.     app.config(['$routeProvider', '$controllerProvider',  
  4.         function($routeProvider, $controllerProvider) {  
  5.             $routeProvider.  
  6.                 when('/module1', {  
  7.                     templateUrl: 'module1/tpl.html',  
  8.                     controller: 'module1Controller',  
  9.                     resolve: {  
  10.                         /* 
  11.                         這個(gè)key值會(huì)被注入到controller中,對(duì)應(yīng)的是后邊這個(gè)function返回的值,或者promise最終resolve的值。函數(shù)的參數(shù)是所需的服務(wù),angular會(huì)根據(jù)參數(shù)名自動(dòng)注入對(duì)應(yīng)controller寫(xiě)法(注意keyName): 
  12.            controllers.controller('module2Controller', ['$scope', '$http', 'keyName', 
  13.                              function($scope, $http, keyName) { 
  14.                          }]); 
  15.                          */  
  16.                         keyName: function ($q) {  
  17.                             var deferred = $q.defer();  
  18.                             require(['module1/module1.js'], function (controller) {  
  19.                                 $controllerProvider.register('module1Controller', controller);      //由于是動(dòng)態(tài)加載的controller,所以要先注冊(cè),再使用  
  20.                                 deferred.resolve();  
  21.                             });  
  22.                             return deferred.promise;  
  23.                         }  
  24.                     }  
  25.                 }).  
  26.                 otherwise({  
  27.                     redirectTo: '/module1'      //angular就喜歡斜杠開(kāi)頭  
  28.                 });  
  29.         }]);  
  30.     return app;  
  31. });  

      上述代碼看起來(lái)長(zhǎng),實(shí)際很短,因?yàn)橛幸欢丫G色的注釋,嘿嘿。。。 

      如果大家用過(guò)angular-route,這里的語(yǔ)法就很簡(jiǎn)單,如果沒(méi)用過(guò),則建議直接閱讀angular-route源代碼中的注釋,非常清晰。 

      簡(jiǎn)單而言,就是when函數(shù)配置一個(gè)路由規(guī)則,對(duì)應(yīng)一個(gè)template和一個(gè)controller。otherwise就是默認(rèn)路由,也就是遇到一個(gè)未定義路徑的時(shí)候如何跳轉(zhuǎn)。 

      如果沒(méi)有使用requirejs,那么我們需要在路由配置前加載完全部controller。angular-route需要做的只是切換HTML模版,重新編譯,綁定新的controller。 

      但是這里用了requirejs,事情就變化了。我們要按需加載,不可能頁(yè)面剛加載就全部controller都load回來(lái),這樣得耗費(fèi)多少流量。。。 

      所以,這里利用了angular-route提供的resolve功能,也就是路由更改html前先把resolve里邊該做的事完成。 

      resolve的寫(xiě)法比較特殊,接受的是一個(gè)key:value對(duì)象,keyName將會(huì)導(dǎo)入到controller中(如果controller有注明依賴)。而value應(yīng)該是一個(gè)函數(shù),函數(shù)的寫(xiě)法類似controller,angular會(huì)自動(dòng)根據(jù)參數(shù)名導(dǎo)入相應(yīng)依賴的服務(wù),例如$q、$route。 

      上述例子中,module1.js定義了模塊1的controller,后續(xù)我們?cè)倏创a。 

      由于路由配置前還不存在這個(gè)controller,所以現(xiàn)在需要?jiǎng)討B(tài)注冊(cè)這個(gè)controller。也就是:

      $controllerProvider.register('module1Controller', controller);

第四步,看看模塊1的controller是怎么寫(xiě)的

[javascript] view plain copy
print?
  1. define(['angular'], function (angular) {  
  2.     //angular會(huì)自動(dòng)根據(jù)controller函數(shù)的參數(shù)名,導(dǎo)入相應(yīng)的服務(wù)  
  3.     return function($scope, $http, $interval){  
  4.         $scope.info = 'kenko';      //向view/模版注入數(shù)據(jù)  
  5.         //模擬請(qǐng)求cgi獲取數(shù)據(jù),數(shù)據(jù)返回后,自動(dòng)修改界面,不需要啰嗦的$('#xxx').html(xxx)  
  6.         $http.get('module2/tpl.html').success(function(data) {  
  7.             $scope.info = 'vivi';  
  8.         });  
  9.         var i = 0;  
  10.         //angularjs修改了原來(lái)的setTimeout和setInterval,要用這兩個(gè)玩意,必須引入$timeout和$interval,否則無(wú)法修改angular范圍內(nèi)的東西  
  11.         $interval(function () {  
  12.             i++;  
  13.             $scope.info = i;  
  14.         }, 1000);  
  15.     };  
  16. });  

      angular有太多牛逼的功能,但實(shí)際上我業(yè)務(wù)太簡(jiǎn)單,用不到。所以這里只演示了3種最簡(jiǎn)單的情況。 

      這里不得不說(shuō),由于雙向綁定,拉cgi和修改dom這些操作就變得非常簡(jiǎn)單了。 

      貌似一切解決了?這樣的模塊化似乎已經(jīng)很好,跳轉(zhuǎn)到某個(gè)模塊的時(shí)候才加載對(duì)應(yīng)的html和controller js。 

      但是對(duì)于追求極致的團(tuán)隊(duì)來(lái)說(shuō),模塊的html和js應(yīng)該打包在一起,一次請(qǐng)求就拉回來(lái),這樣能大大減少HTTP請(qǐng)求的時(shí)間。而現(xiàn)在按照angular-route,只能利用templateUrl單獨(dú)拉取一個(gè)html文件。 

     那么接下來(lái),我們?cè)賱?dòng)動(dòng)歪腦筋,修改一下。

第五步,修改angular-route,實(shí)現(xiàn)HTML和js打包加載。

[javascript] view plain copy
print?
  1. function ngViewFillContentFactory($compile, $controller, $route) {  
  2.   return {  
  3.     restrict: 'ECA',  
  4.     priority: -400,  
  5.     link: function(scope, $element) {  
  6.       var current = $route.current,  
  7.           locals = current.locals;  
  8.       $element.html(current.template);  //原來(lái)是locals.$template  

     首先,先修改一下angular-route的源代碼,這個(gè)源代碼非常精簡(jiǎn),不用太糾結(jié),狠狠的去修改就好了。 

      另外,想問(wèn)我為什么知道或者想到在這修改?咳咳咳,我會(huì)大搖大擺的說(shuō)我認(rèn)識(shí)angular-route的作者么?。。。。。。。開(kāi)玩笑,作者叫什么,我都沒(méi)去找,還說(shuō)認(rèn)識(shí)作者。其實(shí)就是逐步調(diào),稍加變量搜索,發(fā)現(xiàn)一些不對(duì)勁,就做了這個(gè)小刀。 

      再另外,有專家要拍板了,這樣亂修改,肯定帶來(lái)毛病。是的,我不得不說(shuō),我自己都沒(méi)徹底的檢查是否有問(wèn)題,但按照實(shí)際情況來(lái)看,暫時(shí)沒(méi)遇到問(wèn)題。 

      然后,做一個(gè)新的when配置:

[javascript] view plain copy
print?
  1. when('/module2', {  
  2.              template: '',  
  3.              controller: 'module2Controller',  
  4.              resolve:{  
  5.                  keyName: function ($route, $q) {  
  6.                      var deferred = $q.defer();  
  7.                      require(['module2/module2.js'], function (module2) {  
  8.                          $controllerProvider.register('module2Controller', module2.controller);  
  9.                          $route.current.template = module2.tpl;  
  10.                          deferred.resolve();  
  11.                      });  
  12.                      return deferred.promise;  
  13.                  }  
  14.              }  
  15.          })  

      這里用module2做例子,跟module1不同,這里初始設(shè)置的template是空字符串,然后在resolve中require回來(lái)后,動(dòng)態(tài)修改$route.current.template。 

      因?yàn)槲抑?,這個(gè)修改能趕在angular-route修改HTML前,也就是小把戲能湊效。 

     相應(yīng),看看module2怎么寫(xiě):

[javascript] view plain copy
print?
  1. define(['angular', 'text!module2/tpl.html'], function (angular, tpl) {  
  2.     //angular會(huì)自動(dòng)根據(jù)controller函數(shù)的參數(shù)名,導(dǎo)入相應(yīng)的服務(wù)  
  3.     return {  
  4.         controller: function ($scope, $http, $interval) {  
  5.             $scope.date = '2015-07-13';  
  6.         },  
  7.         tpl: tpl  
  8.     };  
  9. });  

      大功告成,這樣html模版就不由angular-route去接管了,而是由requirejs加載,我們可以控制的范圍和靈活性就變大了。 

      不過(guò),這里controller的函數(shù)寫(xiě)法可能會(huì)因?yàn)閴嚎s混淆時(shí)丟失了原來(lái)的參數(shù)名,所以,我們也可以采用顯式注入的方式:

[javascript] view plain copy
print?
  1. //也可以使用這樣的顯式注入方式,angular執(zhí)行controller函數(shù)前,會(huì)先讀取$inject  
  2.    controller.$inject = ['$scope'];  
  3.    function controller(s){  
  4.        s.date = '2015-07-13';  
  5.    }  
  6.    return {controller:controller, tpl:tpl};  

      到這里,整個(gè)架構(gòu)基本就成型了,webapp中每個(gè)模塊都能非常獨(dú)立,這樣對(duì)網(wǎng)站打開(kāi)速度和協(xié)同開(kāi)發(fā)都非常有好處。 

      但是,路由表的配置還是略復(fù)雜,每次大家都要寫(xiě)一大堆代碼,這不是我們想要的,那么可以抽取公用代碼,再優(yōu)化一下。

第六步,優(yōu)化路由表,變成真正的配置化。

[javascript] view plain copy
print?
  1. define(['angular', 'require', 'angular-route'], function (angular, require) {  
  2.     var app = angular.module('webapp', [  
  3.         'ngRoute'  
  4.     ]);  
  5.     app.config(['$routeProvider', '$controllerProvider',  
  6.         function($routeProvider, $controllerProvider) {  
  7.             var routeMap = {  
  8.                 '/module2': {                           //路由  
  9.                     path: 'module2/module2.js',         //模塊的代碼路徑  
  10.                     controller: 'module2Controller'     //控制器名稱  
  11.                 }  
  12.             };  
  13.             var defaultRoute = '/module2';              //默認(rèn)跳轉(zhuǎn)到某個(gè)路由  
  14.             $routeProvider.otherwise({redirectTo: defaultRoute});  
  15.             for (var key in routeMap) {  
  16.                 $routeProvider.when(key, {  
  17.                     template: '',  
  18.                     controller: routeMap[key].controller,  
  19.                     resolve:{  
  20.                      keyName:requireModule(routeMap[key].path, routeMap[key].controller)  
  21.                     }  
  22.                 });  
  23.             }  
  24.             function requireModule(path, controller) {  
  25.                 return function ($route, $q) {  
  26.                     var deferred = $q.defer();  
  27.                     require([path], function (ret) {  
  28.                         $controllerProvider.register(controller, ret.controller);  
  29.                         $route.current.template = ret.tpl;  
  30.                         deferred.resolve();  
  31.                     });  
  32.                     return deferred.promise;  
  33.                 }  
  34.             }  
  35.         }]);  
  36.     return app;  
  37. });  

       routeMap可以由服務(wù)器直出,實(shí)現(xiàn)0緩存,徹底解耦,更便于團(tuán)隊(duì)合作。 

      最后最后,由于requirejs和angular都有模塊管理,但兩個(gè)概念又不一致,這里說(shuō)說(shuō)我的看法:

      requirejs模塊管理,不單單是代碼模塊化,還提供了模塊加載的功能; 

      angular模塊管理,更在乎的是代碼邏輯上的模塊化,避免全局變量污染,并不提供js文件層面的加載功能;

      作為邏輯模塊管理,其實(shí)用requirejs的模塊管理就夠了,所以我覺(jué)得除了angular原生的controller、service外,我們業(yè)務(wù)相關(guān)的公用庫(kù),用requirejs吧。

美文美圖

 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Angular項(xiàng)目構(gòu)建指南 - 不再為AngularJS構(gòu)建而猶豫不決
angular route
AngularJS路由和模板
AngularJS之頁(yè)面跳轉(zhuǎn)Route
Cordova webapp實(shí)戰(zhàn)開(kāi)發(fā)(二)
AngularJS按需動(dòng)態(tài)加載template和controller?
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服