RequireJS简单实用说明
OM前端框架说明
om前端框架采用RequireJS,RequireJS 是一个JavaScript模块加载器。它非常适合在浏览器中使用, 它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJS加载模块化脚本将提高代码的加载速度和质量。
RequireJS 的使用
首先在index.html中引用RequireJs,
<script src="js/lib/require.js" data-main="js/main.js"></script>
注意到图中标签中有一个data-main属性,你现在只需要了解require.js会在加载完成以后通过回调方法去加载这个data-main里面的js文件,所以这个js文件被加载的时候,RequireJS已经加载执行完毕。
require.config({ // http://SMStatic.31huiyi.com/js baseUrl: GLOBAL_CONFIG.SMStaticDomainURL + 'js', urlArgs: 'v=' + (new Date().getTime()), waitSeconds: 30, paths: { 'jquery': 'lib/jquery-2.1.4.min', 'underscore': 'lib/underscore-min', 'backbone': 'lib/backbone-min', 'utils': 'util/utils', 'datatable': 'plugin/datatable/js/datatable', 'lang': 'util/lang-zh_cn', 'validate': 'plugin/jquery.validate.form/js/jquery.validate.form', 'ztree': 'plugin/zTree_v3/js/jquery.ztree.all-3.5.min', 'jqueryui': 'lib/jquery-ui.min', 'printarea': 'plugin/print/jquery.PrintArea', 'autopop': 'app/auto_pop', 'zclip': 'plugin/forms_zclip/jquery.zclip.min', 'calendar': 'app/Ecalendar.jquery.min', 'moment': 'lib/moment', 'bootstrap-datetimepicker': 'lib/datetimepicker', 'newdatetime': 'lib/newdatetime', 'timepicker': 'lib/timepicker_init' }, shim: { 'validate': { deps: ['jquery', 'lang'] }, 'datatable': { deps: ['jquery'] }, 'ztree': { deps: ['jquery'], exports: '$.fn.zTree' } } }); require.onError = function (err) { console.log(err.requireType); if (err.requireType === 'timeout') { console.log('modules: ' + err.requireModules); } throw err; }; require(['base/nav']);
在main.js文件,里面被一个匿名立即执行函数所包括。在require.config(...)中,可以配置许多配置项,后面会有详细说明。上面在config中添加了一个path,在path配置了一个模块ID和路径的映射,这样在后续的所有函数中就可以直接通过模块ID来引入依赖,而不用再多次引入依赖多次输入路径带来的麻烦。当然也可以直接引用相对路径。
知道了大概的requirejs的结构。看看项目里具体怎么使用的吧。
那我们就以在om里获取服务云的公司管理的功能为例。
链接是这样 http://om.31huiyi.com/#/om/ServiceManagement/View/CompanyView
显然这样一个路由是我们自定义的,没有#命名的文件夹。
关于这样一个链接是如何找到companyview.js的呢?
答案在于main.js一开始就加载的nav.js里。看下图
define([ 'jquery', 'backbone', 'util/router', 'base/BaseView', 'app/menunav' ], function($, Backbone, router, BaseView, menu){ var NavView = BaseView.extend({ el: $('body'), root: '#/sm', slideSpeed: 200, events: { 'click .menu > li.has-sub-menu > span': 'foldMenu', //'click .menu > li.has-sub-menu > span': 'routeMenu', 'click .menu .sub-menu > li': 'routeMenu' }, initialize: function() { menu.init(); Backbone.history.start(); }, foldMenu: function(e){ var $T = $(e.target); var SlideSpeed = this.slideSpeed; var $P = $T.parent(); if($P.hasClass('active')){ $('.dy-nav').hide(); $P.removeClass('active'); $P.find('.sub-menu').slideUp(SlideSpeed); } else { $('.menu > li.has-sub-menu').removeClass('active'); $('.menu > li.has-sub-menu').find('.sub-menu').slideUp(SlideSpeed) if($P.find('.sub-menu > li.active').length > 0){ $('.dy-nav').show(); } setTimeout(function(){ menu.reset(); }, SlideSpeed+5); $P.addClass('active'); $P.find('.sub-menu').slideDown(SlideSpeed); } var url = $T.data('url'); if (url) { router.navigate(this.root + url, { trigger: true }); } }, routeMenu: function(e){ var $T = $(e.currentTarget); var url = $T.data('url'); if(url){ $('.menu .sub-menu > li').removeClass('active'); $T.addClass('active'); var top = $T.offset().top; var _html = '<div class="loading-view"></div>'; if($('.loading-view').length === 0){ $('body').append(_html); } $('.loading-view').css({ display: 'block', top: top + ($T.height()-$('.loading-view').height())/2 }); router.navigate(this.root+url, {trigger: true}); } } }); return new NavView; });
define([ 'jquery', 'backbone', 'app/menunav' ], function ($, Backbone, menu) { var Router = Backbone.Router.extend({ currentView: null, root: GLOBAL_CONFIG.CurrentDomainScriptPath, routes: { '': 'transmitRouter', 'sm/*path': 'transmitRouter', '*error': 'error' }, switchView: function(hash, view){ var curLi = $('.menu').find('[data-url="/'+hash+'"]'); curLi.parents('.has-sub-menu').addClass('active'); curLi.addClass('active'); menu.active(curLi); if(this.currentView){ this.currentView.remove(); } this.currentView = view; }, transmitRouter: function(hash){ var _this = this; // DefaultPage变量在Index.cshtml里配置 if (!hash) hash = GLOBAL_CONFIG.DefaultPage; require([_this.root + hash + '.js'], function (View) { var view = new View; _this.switchView(hash, view); }); }, error: function(){ alert('页面未找到'); $('.loading-view').hide(); } }); return new Router(); });
定义了root,然后在所有的菜单的链接上都加上root.而在router.navigate这个方法里会找到companyview的绝对地址。
接下来看看companyview的结构是怎样的?
define = function (name, deps, callback)完成的,第一个参数是定义模块名,第二个参数是传入定义模块所需要的依赖,第三个函数则是定义模块的主函数,主函数和require的回调函数一样,同样是在依赖加载完以后再调用执行。通常第一个参数我们会不写,以防我们会转移这个文件的目录,让优化工具自己生产这些模块名。
define([ 'jquery', 'base/BaseView', 'app/ztree', 'utils', '/script/OM/ServiceManagement/Model/CompanyModel.js', 'datatable', 'validate' ], function ($, BaseView, zTree, utils, CompanyModel, DataTable) { var CompanysView = BaseView.extend({ model: CompanyModel, url: CompanyModel.initurl, dt: null, events: { 'click #SearchByFansName': 'Search', 'click #addCompany': 'addCompany', 'click #searchUserBtn': 'searchUserBtn', 'click #saveModel': 'saveUserCompany' }, outerEvents: {}, initialize: function () { var _this = this; this.bindOuterEvent(); this.render({ complete: function () { _this.initTable(); } }); });
下面我们讲讲这些参数的具体用法。
Model:在本次项目中我们把Controllers的操作方法的路由存到model里去。便于管理,上面要引用这个路径。
Url:是当前页面的路由。
Dt:初始化为null,如果页面里有列表数据,会在initTable赋值。
Events:就是当前页面触发的事件。
OutEvents:就是公共事件
Initialize: 初始化这个页面执行的方法。
OK,om的前端框架大致就是这样了。