Sea.js是模块开发的前端开源框架,他解决了繁琐的文件依赖关系带来的问题,繁琐文件依赖带来的问题如下(Sea.js官网):
- 通用组更新了前端基础类库,却很难推动全站升级。
- 业务组想用某个新的通用组件,但发现无法简单通过几行代码搞定。
- 一个老产品要上新功能,最后评估只能基于老的类库继续开发。
- 公司整合业务,某两个产品线要合并。结果发现前端代码冲突。
- ……
技术的发展是在解决一个又一个的问题,话不多说先进入使用的实例中吧。以下实例为jsp前端请求后台数据的实现过程,他涉及到俩个模块,一个为业务模块,另一个模块封装了请求接口汇总,俩个文件分别为patient_category.js和AppService.js。实现代码如下:
a、patient_category.jsp
<script type="text/javascript">
seajs.use('${ctx}/view/module/patients/j/patient_category', function (patientCategory) {
patientCategory.renderNav();
});
</script>
b、patient_category.js
define(function (require, exports, module) {
var Utils = require('vl/j/util');
var template = require('lib/template.js');
var AppService = require('vl/j/AppService');
var service = new AppService();
var patientCategory = {
init: function () {
$("#myLayout").zoeLayout({
leftWidth: 200,
onEndResize: function () {
$("#tree").width("100%");
}
});
var _sel = this;
$(function () {
_sel.initEvent();
setTimeout(function () {
_sel.setContainerH();
}, 50);
})
},
initEvent: function () {
var _sel = this;
this.resize();
$('.acc-tit i').on('click', function () {
var $ml = $('.main-left');
var $mr = $('.main-right');
// main-left width
var mlw = parseFloat($ml.css('width'));
// main-right width
var mrw = parseFloat($mr.css('width'));
// main-ringht margin left
var mrml = parseFloat($mr.css('margin-left'));
if ($(this).hasClass('closed')) {
$ml.animate({width: mlw + 170});
$mr.animate({width: mrw - 170, marginLeft: mrml + 170});
$(this).removeClass('closed').siblings().fadeIn();
} else {
$ml.animate({width: mlw - 170});
$mr.animate({width: mrw + 170, marginLeft: mrml - 170});
$(this).addClass('closed').siblings().fadeOut();
;
}
$('#tree').slideToggle();
})
},
mergeCode: function (tree, code, first) {
var _sef = this;
$.each(tree, function (idx, node) {
var needAnd = first ? '' : '&';
node.code = code + needAnd + node.code + "=" + node.id;
if (node.children && node.children.length > 0) {
_sef.mergeCode(node.children, node.code, false);
}
});
},
success: {
menu: function (result) {
var _sef = patientCategory;
$.each(result, function (idx, item) {
if (item.code == 'diseaseId') {
item.uri = 'patients/v/list'
}
});
result = Utils.treeDataFilter(result, null, 'name', null);
_sef.mergeCode(result, '', true);
$('#tree').zoeTree({
nodeWidth: 200,
data: result,
checkbox: false,
idFieldName: 'id',
btnClickToToggleOnly:false,
isExpand: false,
iconFieldName: 'remark',
slide: true,
//attribute:['id','text'],
onClick: function (treeNode) {
var hasChildren = $("#tree").zoeTree().hasChildren(treeNode.data);
var uri = treeNode.data.uri;
if (uri) {
var nodeUri = uri.indexOf('http://')==0 ? uri : window.ctx + "/" + uri;
var paramSplit = nodeUri.indexOf('?') == -1 ? '?' : '&';
nodeUri = nodeUri + paramSplit + treeNode.data.code;
$('#treeContent').attr('src', nodeUri);
}
if (hasChildren) {
// 如果是父级,
}
}
});
/* var menu = template("menuTemplate", data);
$('.main-left').html( $('.main-left').html() + menu );*/
_sef.init()
}
},
renderNav: function () {
var _sef = this;
service.request('menu', {success: _sef.success.menu});
},
/**
* 高度自适应
*/
resize: function () {
var _sel = this;
$(window).resize(function () {
_sel.setContainerH();
});
},
/**
* 设置容器高度
*/
setContainerH: function (adjustTopMenu) {
//var size=page.getSize();
//console.log(size)
var wh = $(window).height() - 2;
$(".main").height(wh);
$(".main-left").height(wh);
// $(".main-right").height(wh);
if ($("#maingrid").zoeGetGridManager()) {
$("#maingrid").zoeGetGridManager().options.height = wh - 47;
}
if ($("#datagrid").zoeGetGridManager()) {
$("#datagrid").zoeGetGridManager().options.height = wh - 47;
}
}
};
module.exports = patientCategory;
});
通过require("")可获取文件。
moudule.export将对象暴露出去,这样可以将不允许外界访问的资源隐藏起来。
C、AppServices.js的实现
define(function (require, exports, module) {
var ajax = require('vl/j/ajax');
var AppService = function () {
/**
* 后台请求接口汇总
* @type {{menu: {type: string, url: string}, patientList: {type: string, url: string}, patientPanelTab: {type: string, url: string}, patientBaseInfo: {type: string, url: string}, patientDiagnosisList: {type: string, url: string}, example: {type: string, url: string}}}
*/
this.api = {
//----------------------------------------------------------------------------------
// ----------------------------- 患者模块接口汇总 --------------------------------
//----------------------------------------------------------------------------------
// 患者管理导航导航
'menu': {type: 'get', url: window.ctx + '/patients/menu'},
//我的工作台患者管理导航
'myPatientsMenu': {type: 'get', url: window.ctx + '/myPatients/menu'},
// 病人列表
'patientList': {type: 'post', url: window.ctx + '/patients/query'},
// 病人面板的标签 基本信息、检验、检查等
'patientPanelTab': {type: 'post', url: window.ctx + '/patient_function/getChild'},
// 患者基本信息
'patientBaseInfo': {type: 'post', url: window.ctx + '/patients/byId'},
// 患者诊断列表
'patientDiagnosisList': {type: 'post', url: window.ctx + '/patients/diagnosisQuery'},
// 个案患者诊断基本信息
'patientDiagnosisInfo': {type: 'post', url: window.ctx + '/patients/diagnosisInfo'},
//'patientDiagnosisList': { type: 'get', url: window.ctx + '/view/module/patients/t/patientDiagnosisList.json' },
// TODO 患者检查列表
'patientCheckUpList': {type: 'post', url: window.ctx + '/patients/queryExam'},
// TODO 患者检验列表
'patientCheckoutList': {type: 'post', url: window.ctx + '/patients/queryLab'},
//----------------------------------------------------------------------------------
// Grid 列表字段采用字典时,获取字典
//----------------------------------------------------------------------------------
'dict': {type: 'post', url: window.ctx + '/sys_base_dict/getSysBaseDictData'},
//----------------------------------------------------------------------------------
// 接口格式例子
//----------------------------------------------------------------------------------
'example': {type: 'get', url: window.ctx + '/assets/serverMock/index/menu.json'},
//----------------------------------------------------------------------------------
// 专病字典
//----------------------------------------------------------------------------------
'dictDisease': {type: 'get', url: window.ctx + '/dmp_form_dict/menu'}
};
return this;
};
AppService.prototype = {
/**
* 通过 请求id, 与请求参数,获取服务器的数据
*
* 这么写的好处就是 后台接口还没有的话,直接用 json ,后面接口完成后,批量替换接口地址,
* 前后端开发相对独立
*
* @param requestId 请求 id, 用于获取 this.api 中的参数
* @param config ajax 请求参数
*/
request: function (requestId, config) {
var option = this.getApi(requestId);
$.extend(config, option);
ajax.ajax(config);
},
/**
* @desc 通过 请求id 获取 this.api 中的后台接口参数,
* 普通 ajax 请求只被 request 调用,
* 在 ligerUI 插件中,自己不需要实现事件回调的地方,单独被调用
*
* @param requestId 请求 id, 用于获取 this.api 中的参数
* @param typeName 请求方式的属性名称,
* 如:普通ajax 请求方式属性名 type,此时可为空。{ type: 'GET', url: '/example' }
* ligerUI控件中,请求方式属性名为 method, 此时传入 method , 返回结果 { method: 'GET', url: '/example' }
* @returns {*}
*/
getApi: function (requestId, typeName) {
var option = this.api[requestId];
if (typeName) {
option[typeName] = option.type;
}
'type' != typeName && delete option.type;
return option;
}
};
module.exports = AppService;
});