前端模塊化
模塊化實際上我們並不陌生。例如,應用函數,應用類等進行封裝。但是相對來說,以往的前端並沒有很明顯的模塊化的概念。這樣導致了有幾個弊端。
1 分類不清晰。合作開發頻繁衝突。
2 全局變量污染。
全局變量就是在所有作用域中都可見的變量。全局變量在很小的程序中可能會帶來方便, 但隨着程序越來越大,它很快變得難以處理。因爲一個全局變量可以被程序的任何部分在任意時間改變,使得程序的行爲被極大地複雜化。在程序中使用全局變量降 低了程序的可靠性。全局變量使在同一個程序中運行獨立的子程序變得更難。如果某些全局變量的名稱與子程序中的變量名稱相同,那麼它們將會相互衝突並可能導致程序無法運行,而且通常還使程序難以調試。
因此我們稱之爲全局變量污染。那麼如果進行了模塊化,將變量作用域定義爲某個特定的模塊內,就避免了類似的問題發生。
模塊化的幾種技術
RequireJS 和 SeaJS
RequireJS 和 SeaJS 等等都是很不錯的模塊加載器兩者區別如下:
1. 兩者定位有差異。 RequireJS 想成爲瀏覽器端的模塊加載器,同時也想成爲 Rhino / Node 等環境的模塊加載器。SeaJS 則專注於 Web 瀏覽器端,同時通過 Node 擴展的方式可以很方便跑在 Node服務端。
2. 兩者遵循的標準有差異。 RequireJS 遵循的是 AMD(異步模塊定義)規範,SeaJS 遵循的是 CMD (通用模塊定義)規範。規範的不同,導致了兩者 API 的不同。SeaJS 更簡潔優雅,更貼近 CommonJS Modules/1.1 和 Node Modules 規範。
3. 兩者社區理念有差異。 RequireJS 在嘗試讓第三方類庫修改自身來支持 RequireJS,目前只有少數社區採納。SeaJS 不強推,而採用自主封裝的方式來“海納百川”,目前已有較成熟的封裝策略。
4. 兩者對調試等的支持有差異。 SeaJS 通過插件,可以實現 Fiddler 中自動映射的功能,還可以實現自動 combo 等功能,非常方便便捷。RequireJS 無這方面的支持。
5. 兩者的插件機制有差異。 RequireJS 採取的是在源碼中預留接口的形式,源碼中留有爲插件而寫的代碼。SeaJS 採取的插件機制則與 Node 的方式一致:開放自身,讓插件開發者可直接訪問或修改,從而非常靈活,可以實現各種類型的插件。
還有不少細節差異就不多說了。
在實際項目中我們選用了requireJs 進行了模塊化管理。
接下來,就以一個最爲簡單的ionic實例來演示如何加入require.js實例。
準備工作
創建示例,我創建了一個ionic 默認實例。
它的目錄結構大家都很熟悉了。
模塊化
接下來我們就以該示例爲例,應用requireJs 進行模塊化整理。
就先拿controllers.js開刀。首先我們看controllers.js的內容我們可以分爲4個controller。分別爲 DashCtrl.js ,ChatsCtrl.js,ChatDetailCtrl.js,AccountCtrl.js
1)新建controllers文件夾
然後在controllers文件夾下新建DashCtrl.js文件。
①修改DashCtrl.js文件
上圖中該DashCtrl部分並沒有任何方法。那麼把它移到DashCtrl.js中,並讓其符合require.js格式。則改爲:
define([], function () {});
不過爲了咱們的演示效果,我在這個方法裏執行了一個賦值過程。
//dashCtrl.js content:
define([], function () {
'use strict';//以"嚴格模式"運行
function ctrl($scope) {
$scope.greet = "hello world";
}
return ctrl;
});
備註:這個controller就改好了。別的controller內容仍然不變,只是更改其符合爲requirejs的格式即可。爲了簡化內容。咱們就不做這些功能了。我直接將其刪除了。
②修改controller.js
先將原來的controllers.js移到controllers文件夾下面。
現在controller的目錄爲如下。
打開controllers.js ,需要將我們分開的幾個使用require管理的controller 都彙總起來。其格式也是遵循requireJs
//controllers.js content:
define(function (require) {
'use strict';
var controllers = angular.module('starter.controllers', []);
//controllers.controller('controller名字',require(對應的文件地址));
controllers.controller('DashCtrl',require('controllers/dashCtrl'));
return controllers;
});
備註:實際應用中也需要對serverjs進行模塊化。其模塊化過程和controller的模塊過程一模一樣。還是爲了簡化演示的流程,我們在這裏就不展開了。因爲示例數據並沒有應用services.js 咱們還是簡單粗暴的將其刪除。
2)添加requireJs
添加文件:下載requireJs文件,將其放在了www-js 下面。
添加引用:在index.html文件中將對其的應用添加上。
同時設置其屬性data-main=”js/main.js” 意爲程序入口從main.js啓動。
刪除引用:因爲我們已經設置了從main.js啓動,所以在頁面中將其原本對app.js controller.js services.js的引用刪除
3)設置啓動文件
①在www-js 下新建文件main.js
其內容如下:
// contents of main.js:
require.config({
baseUrl:'js',//基目錄
deps: [
'bootstrap'//啓動
]
});
②在www-js 下新建文件bootstrap.js文件
其內容如下:
/*global define, require, console, cordova, navigator */
define(['app'], function (app) {
'use strict';
//方案1:如果不好理解下面的內容可以直接
// angular.bootstrap(document, [app.name]);
//這部分是方案1的內容
//方案2
angular.element(document).ready(function () {
console.log("bootstrap ready");
var startApp = function () {
angular.bootstrap(document, [app.name]);
}
var onDeviceReady = function () {
console.log("on deviceready");
angular.element().ready(function () {
startApp();
});
}
if (typeof cordova === 'undefined') {
startApp();
} else {
document.addEventListener("deviceready", onDeviceReady, false);
}
//這一部分是方案2的內容
});
});
③修改app 符合爲requirejs格式。
同時我簡化了路由。只配置了index頁面。其內容如下。
define(['controllers/controllers'],
function () {
'use strict';
var app = angular.module('starter', ['ionic', 'starter.controllers'])
app.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state("index",{
url:"/index",
templateUrl:"index.html",
controller: 'DashCtrl'
})
$urlRouterProvider.otherwise('/index');
});
return app;
});
4) 顯示
我們在頁面上顯示我們在DashCtrl方法中的賦值。
即在index頁面 節點下添加
<h2> {{greet}}</h2>
最終結果
5)總結
應用requireJS進行模塊化,也就是應用其將原本一個文件裏的東西進行分離。在本文示例中,我們通過requireJS將原本在一個controllers文件裏的東西進行了分離。其所有的實現都不改變。再實際應用中,還需要對servicesJs進行模塊化等。總之,其實現思路是一致的。分離,注入,設置啓動項。
此外,以下幾篇博客也是關於ionic項目的相關講解,推薦給大家。
ionic入門教程第三課-在項目中使用requirejs分離controller文件和server文件
ionic入門教程第四課-使用$controllerProvider按需加載controller