首先認識requirejs
requirejs是個包加載器,核心功能是模塊化管理,可以實現按需加載。 重點是明白 模塊化不是按需加載。
模塊化的意義: 是通過代碼邏輯表明模塊之間的依賴關系和執行順序,按照模塊邏輯來分解代碼,起到配合mvc框架架構項目的作用。
按需加載:顧名思義 根據需要 通過模塊依賴 event事件 加載所需的模塊。
因為做的本地混合應用,在我項目中的主要的作用是模塊化,我使用requirejs的原因是模塊化管理,不是按需加載。
backbone 配合 requirejs 架構前端方案 https://github.com/breakfriday/backboneMvc-requirejs
backbone是非常經典的前端mvc框架 除了mvc幾乎沒有其他功能。
如果用backbone這一類框架 架構項目 流程:
上圖 可以看到
backbone一類框架的流程 路由驅動控制器(此處增加backboneMvc插件 backbone本身沒有控制其邏輯) 控制器驅動action action完成對應的視圖模塊與model模塊的調用,保證多個視圖模塊與model之間的通信
模塊結構 入口文件調用module a,module a調用module b,依次 module b 調用 c ,e , f ... 完成模板的編譯 事件的綁定 viewMode的組裝 ..... 最后生成視圖對象 render。
ctrl1 通過require([],function(){})可以實現按需加載
define(function (require) {
BackboneMVC = require("BackboneMVC")
$ = require("jquery")
_ = require("underscore")
return function(){
BackboneMVC.namespace('MyApp.Controllers');
MyApp.Controllers.ToyController = BackboneMVC.Controller.extend({
name: 'ct1', /* the only mandatory field */
index: function () {
alert("ct1")
},
test1: function () {
require(['model/model'],function(model){
model.init().done(function () {
$(".pages").append("<div style='color: red'>test0 done " + model.name+"</div>")
}).fail(function () {
alert("not ok")
})
this.model=undefined
}.bind(this))
},
test2: function () {
require(["model/model2", "view/view2"], function (model, view1) {
var model = this.model = this.model || new model
model.init().done(function () {
view1.sucess(model.name)
this.test2()
}.bind(this)).fail(function () {
view1.fail()
}).progress(function () {
view1.progess()
})
}.bind(this))
}
});
}
});
或者 對比ctrl2流程邏輯與ctrl1相同,ctr2l使用commonjs的寫法require() 其實是標注模塊的依賴性,進define頭,一次性加載。 requirejs 支持commonjs的語法 但是使用的是amd的協議
define(function (require) {
BackboneMVC = require("BackboneMVC")
$ = require("jquery")
_ = require("underscore")
return function(){
BackboneMVC.namespace('MyApp.Controllers');
MyApp.Controllers.ToyController = BackboneMVC.Controller.extend({
name: 'ct2', /* the only mandatory field */
index: function () {
alert("this is ct2")
},
test1: function () {
var model=require('model/model')
model.init().done(function () {
$(".pages").append("<div style='color: red'>test0 done " + model.name+"</div>")
}).fail(function () {
alert("not ok")
})
this.model=undefined
},
test2: function () {
var model=require("model/model2")
var view1=require("view/view2")
var model = this.model = this.model || new model
model.init().done(function () {
view1.sucess(model.name)
if (model.name > 1) {
this.test2()
}
}.bind(this)).fail(function () {
view1.fail()
}).progress(function () {
view1.progess()
})
}
});
}
});
這是我 requirejs + backbone 架構項目的結構。
用angular已經做了兩個項目了,這里總結下
angular 框架執行流程: 前端方案 https://github.com/breakfriday/my-angularMvc
郁悶的是經常有人說 angular 已經有module了還需requirejs嗎, angular的module 是命令的容器 與模塊化意思不同。
angualr的模塊化只是解決了 代碼邏輯的耦合性的問題,沒有通過原型鏈 class這一種方法來實現,而是通過依賴注入代替class,優點是耦合性很散可以很方便的拆分組合。
但是requirejs另一部功能,控制模塊文件的加載,控制模塊文件的分割,控制模塊文件的依賴關系 這一部分邏輯是angular沒做的。
angular使用requirejs
1.打包方便, 使用requrejs 模塊化 ,編輯代碼的過程就定義了模塊之間的依賴關系,打包時候,不需要一個一個文件對照,用不到沒有依賴關系的文件不會被打包,也不會漏掉文件。
2.將script 腳本從模板頁面(針對mvc框架)抽離出來,通過js當前模塊加載需要依賴的js模塊。模板頁面只是模板。
3.可以實現 按需加載
angular 使用命令式編程的一個框架,所以在耦合性上采用了依賴注入 ,流程與backbone一類 框架不一樣 ,流程執行不是通過controller model view模塊之間的調用,而是通過模板中的命令驅動。
首先認識 angular
app.js angular啟動文件
define([
'angular',
"controller/controllers",
"directive/directives",
"filter/filters",
"angularRoute"
], function (angular,controllers,directives,filiters) {
var webApp=angular.module('ccmsApp', ["ngRoute",controllers.name,directives.name,filiters.name])
})
main.js requirejs配置文件 手動啟動angular
require([ 'angular', 'script/app',"jquery"], function (angular, app) {
angular.element().ready(function () {
angular.resumeBootstrap([app['name']]);
});
})
模塊的注入方式分為 1. 按需加載 2.預加載 兩種方案
在我的項目中,
directive service使用預加載,優點可以合並壓縮成一個文件 減少http請求。且我的directive service 文件比較多很多是小文件,且各個視圖都會用到,不太好從視圖的邏輯來分割加載模塊文件。
controller 是按需加載, 優點按需加載,因為controller 處理的就是viewModel 所以控制器文件與視圖關系是多對一,可以從視圖的邏輯來分割加載模塊文件。缺點是因為是異步模塊,所以不進amd 依賴關系不會被打包,
需要再寫個built1.js 負責壓縮整個異步模塊的目錄
service預加載:
define(function(require){
var angular=require("angular")
var accountService=require("service/script/accountService")
var ngCustomListService=require("service/script/ngCustomListService")
var ngCustomService=require("service/script/ngCustomService")
var saveService=require("service/script/saveService")
var getListService=require("service/script/getListService")
var deleteService=require("service/script/deleteService")
var RFMTreeService=require("service/script/RFMTreeService")
var queryConfigService=require("service/script/queryConfigService")
var dataTableConfigService=require("service/script/dataTableConfigService")
var dataFilterConfigService=require("service/script/dataFilterConfigService")
var ngRedAndBlackCustomService=require("service/script/ngRedAndBlackCustomService")
var productLabelService=require("service/script/productLabelService")
var ngDataImportService=require("service/script/ngDataImportService")
var dataService=angular.module('dataServices', [])
dataService.factory({
"ngCustomListService":ngCustomListService ,
"ngCustomService":ngCustomService,
"saveService":saveService,
"getListService":getListService,
"deleteService":deleteService,
"accountService":accountService,
"queryConfigService":queryConfigService,
"dataTableConfigService":dataTableConfigService,
"dataFilterConfigService":dataFilterConfigService,
"RFMTreeService":RFMTreeService,
"ngRedAndBlackCustomService":ngRedAndBlackCustomService,
"productLabelService":productLabelService,
"ngDataImportService":ngDataImportService
})
return dataService;
})
按需加載:
使用angular 路由的resolve api,在路由啟動時,require 對應的ngView視圖模板頁面中所需的controller directive模塊。
通過$controllerProvider.register $compileProvider.directive $filterProvider.register $provide.provider創建controller directive filter service 依賴模塊。
resolve阻塞,保證對應視圖中的命令(controller,directive,filiter) 注入完成后再run
function config(templateUrl, controllerName, directives) {
if (!$controllerProvider) {
throw new Error("$controllerProvider is not set!");
}
var defer,
html,
routeDefinition = {};
routeDefinition.templateUrl =templateUrl
routeDefinition.controller = controllerName;
routeDefinition.resolve = {
delay:function ($q, $rootScope) {
defer = $q.defer();
var dependencies = [controllerName];
if (directives) {
dependencies = dependencies.concat(directives);
}
require(dependencies, function () { //按需加載 所需的控制器 directives 模塊 ,
// 通過$controllerProvider.register $compileProvider.directive創建
var controller = arguments[0],
template = "";
for (var i = 2; i < arguments.length; i++) {
lazyDirectives.register(arguments[i]);
}
$controllerProvider.register(controllerName, controller); /*創建控制器*/
html = template;
defer.resolve(); /*加載完 返回resolve狀態*/
$rootScope.$apply()
})
return defer.promise;
}
}
return routeDefinition;
}
$routeProvider.when('/view2', routeConfig.config('./partials/view2.html', 'controllers/second', ['directives/version']));
