seajs+backbone實現單頁面應用模塊自動加載


這不是一篇介紹seajsbackbone的文章,如果對這兩個庫不太了解,可以去他們官網查閱。歡迎轉載,注明出處:http://www.cnblogs.com/mapping/archive/2013/03/03/2941812.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

 

歡迎轉載,注明出處:http://www.cnblogs.com/mapping/archive/2013/03/03/2941812.html

 

 

 

 


免責聲明!

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



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