您的位置:首页 > Web前端 > JavaScript

seajs+backbone实现单页面应用模块自动加载

2015-01-11 17:43 435 查看
这不是一篇介绍seajsbackbone的文章,如果对这两个库不太了解,可以去他们官网查阅。欢迎转载,注明出处:/article/5545883.html

单页面应用(spa:single page application)的业务逻辑多是比较复杂的,如果一次性把整个spa用到的文件加出估计得卡到不行,使用seajs可以很好的实现按需加载;使用backbone可以比较方便地实现数据、逻辑、表现分离,有人称他为前端的MVC框架,又有人说他不算是MVC,这里就不做讨论。

本文主要讲解如何使用这两个库实现spa里模块根据路由的自动加载

首先建立整个app的文件结构,如图:



根目录:autoload;

根目录下index.html作为app首页及入口,js目录放置app的js文件;

js目录中base放置基本的依赖js库,main目录放置app的框架代码,module目录就是用来放置各个模块的功能js啦;

下一步就是把underscore、jquery、backbone源码包装成CMD规范(或参考这里)的文件,underscore和backbone已内置AMD接口,jquery最新版也已添加AMD的exports接口,如果是旧版的jquery需要return
$.noConfilt(true),如下:

base/jquery.js

define('base/jquery', function(require) {
//jquery官方源码
return $.noConflict(true);
});


base/underscore.js

define('base/underscore', function(require, exports, module) {
//underscore官方源码
});


base/backbone.js

define('base/backbone', ['underscore', '$'], function(require, exports, module) {
this._ = require('underscore');
this.jQuery = require('$');
//backbone官方源码
});


用过backbone的人都知道,使用他的路由功能来做spa非常方便,页面较少的情况还可以,如果页面一多,每次都要改路由配置;虽然backbone也支持多个Router对象,但每次新增模块还是避免不了增加对应的router规则,就需要维护多个文件;而且配置的router越多,出现重复的概率就会越大,所以我们就要制定一个统一的router规则来实现模块自动加载,其实就是把模块的功能文件路径及文件名作为参数传给router处理函数,然后使用seajs的require.async方法去加载对应的文件,如下:

main/app.js

define('main/app', function(require, exports) {
var Backbone = require('backbone');

//配置路由
var autoRouter = Backbone.Router.extend({
routes: {
'': 'home',
'at/:module/:action(/*condition)': 'loadmodule'
},
home: function() {
this.loadmodule('home', 'index');
},
//按照at/module/action(/conditions)格式的請求自動加載模塊
loadmodule: function(md, ac, con) {
//将参数字符串'a:123/b:456'转换为json对象{a:123, b:456}
var cj = {};
if(con && con.indexOf(':') > -1) {
con.replace(/(\w+)\s*:\s*([\w-]+)/g, function(a, b, c) {
b && (cj[b] = c);
});
} else {
cj = con;
}
//加载module目录下对应的模块
require.async(['module', md, ac].join('/'), function(cb) {
if(cb) {
cb(cj);
} else {
alert('模塊加載失敗!');
}
})
}
});

//定义全局变量App
window.App = {
Models: {},
Views: {},
Collections: {},
initialize: function() {
new autoRouter();
Backbone.history.start();
}
};

exports.run = App.initialize;
})


这里给路由一个非常yy的名称at(把模块@出来^_^),任何匹配'at/:module/:action(/*condition)'规则的路径都会调用loadmodule方法,在这里condition是一个可选参数,如果要传递多个参数可以写成‘a:123/b:456’的格式,loadmodule方法会将这个格式字符串转换成json方便模块里的代码调用

autoRouter对象中还有一个空路由用于app的启动,实际这条路由相当于'at/home/index';我们现在要做的就是在module目录里加模块文件了:

module/home/index.js

define('module/home/index', ['backbone'], function(reuqire) {
var Backbone = reuqire('backbone');
App.Models.Home = Backbone.Model.extend({});

App.Collections.Home = Backbone.Collection.extend({
model: App.Models.Home
});

App.Views.Home = Backbone.View.extend({
el: '#container',
initialize: function(c) {
this.Collections = c;
this.render();
},
render: function() {
var html = '';
this.Collections.each(function(m) {
html += '<div><a href="' + m.get('link') + '">' + m.get('name') + '</a></div>';
});
this.$el.html(html);
}
})

return function() {
//模拟数据
var hc = new App.Collections.Home();
hc.add([
{'name': '加载模块A', 'link': '#at/m/a/name:moduleA/other:nothing'},
{'name': '加载模块B', 'link': '#at/m/b'}
]);
new App.Views.Home(hc);
}
});


注意:每个自动加载的模块都必须返回一个function,用于loadmodule方法callback,否则,提示模块加载失败;

这个function一般都用来将加出来的模块初始化,如上面的index.js,这里会在页面添加两个链接用来加载模块A和模块B,再看下页面index.html的代码:

index.html

<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>seajs+backbone实现单页面模块自动加载</title>
</head>
<body>
<div id="container">
</div>
<script type="text/javascript" src="js/base/sea.js"></script>
<script type="text/javascript">
seajs.config({
base: '/js/',
alias: {
//基础库
'underscore': 'base/underscore',
'$': 'base/jquery',
'backbone': 'base/backbone',
'app': 'main/app'
}
});
seajs.use('app', function(app) {
app.run();
});
</script>
</body>
</html>


到这里,整个app已经可以运行啦



但是点击“加载模块A”或“加载模块B”都会弹出模块加载失败,那是因为我们还没添加这两个模块

module/m/a.js

define('module/m/a', ['$'], function(reuqire) {
var $ = reuqire('$');
return function(c) {
alert('moduleA加载成功,参数:' + $.param(c));
}
});


加载模块A运行结果:



module/m/b.js

define('module/m/b', ['$'], function(reuqire) {
return function(c) {
alert('moduleB加载成功,参数:' + c);
}
});


加载模块B运行结果:



好了,我们整个demo已经结束了,本文只是简单介绍一种模块自动加载的思路。

如果是做一个完整的spa,那么还有模块依赖的样式css文件、模板html文件需要加载以及从api拉取数据,这些功能借助seajs和backbone都可以比较方便实现,加载模板html文件你或许需要seajs的plugin-text.js插件

本文demo打包下载:autoload.zip

欢迎转载,注明出处:/article/5545883.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: