在前端的工作业务场景中,不可避免的需要使用传统的方式编写业务代码,或者重构优化之前的项目的代码。或者有些前端小伙伴(包括我),因为各种原因,大部分的工作还是以传统的方式进行。
本文也在进行一种尝试或者说探索,希望传统的开发方式,更加的规范化。
先看HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./bluebird.core.min.js"></script>
<script src="./axios.min.js"></script>
<script src="./qs.min.js"></script>
<script src="./mogenshixiong.js"></script>
</body>
</html>
引入: bluebird.js 使得IE兼容 Promise 语法。
引入: axios.js qs.js 用来管理 http 请求
mogenshixiong.js 封装项目的公用代码。
mogenshixiong.js 代码结构如下:
var m = {
utils: {}, // 公共工具函数
logger: {}, // 日志采集
catch: {}, // 异常捕获
apiList: {}, // 维护当前项目的所有api
api: function(){}, // 封装请求方法
const: {}, // 常量定义
status: {}, // 公共状态
commonInit: function(){}, 公共初始化方法
data: {}, // 页面状态,写在引用页面
controller: {}, // 页面逻辑方法,写在引用页面
server: {}, // 页面实现方法,写在引用页面
}
HTML页面在使用demo如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./bluebird.core.min.js"></script>
<script src="./axios.min.js"></script>
<script src="./qs.min.js"></script>
<script src="./mogenshixiong.js"></script>
<script>
window.onload = function(){
m.commonInit(); // 执行公共初始化方法
m.controller.initData(); // 初始化 data
m.controller.initPage(); // 执行页面初始化方法
}
m.controller = { // 页面中的所有业务逻辑方法写在controller内
initData: function(){
m.data = { // 页面数据管理
user: {}
}
},
initPage: function(){ //页面初始化,(使用链式调用,获取异步数据)
m.controller.getUser();
},
getUser: function(){ // 获取用户信息
m.api('getUser', {}, {}).then(function(res){
m.data.user = res;
m.controller.getMessageByUser();
});
},
getMessageByUser: function(){ // 获取用户消息列表
m.api('getMessageByUser', {}, {id: m.data.user.id}).then(function(res){
m.server.initMessageTableHtml(res);
});
},
}
m.server = { // 页面中所有非逻辑的实现类方法写在server内
initMessageTableHtml: function(res){ // 拼接消息列表HTML
messageTable.innerHTML = 'list';
},
}
</body>
</html>
通过 业务逻辑和 实现代码 分离的管理方式。在复杂的页面中,可以让代码更加的清晰。
在具体的实现中可以根据 项目的 兼容性及 其他方面的考虑,可以灵活的扩展。这里只提供一个思路。
以下是 mogenshixiong.js 代码的基础实现。可以在项目中逐步扩展。
var m = {
utils: { // 工具类函数
browser : { //浏览器功能
getUrlParam : function(name, origin) { // 获取URL参数 m.utils.browser.getUrlParam('id')
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = null;
if (origin == null) {
r = window.location.search.substr(1).match(reg);
} else {
r = origin.substr(1).match(reg);
}
if (r != null) return decodeURIComponent(r[2]);
return null;
},
},
valueType : { // 数据类型
isJSON : function(str) { // 判断是否为JSON字符串 m.utils.valueType.isJSON('string')
if (typeof str == 'string') {
try {
var obj = JSON.parse(str);
if (typeof obj == 'object' && obj) {return true;} else {return false;}
} catch (e) {
return false;
}
} else {
return false;
}
},
},
},
logger: { // 日志采集
console: function(o){ console.log(o); },
error: function(err) { console.log(err); },
},
catch: {}, // 异常捕获
apiList: {// api 维护当前项目的所有api
getUser: {path: '/getUser', method: 'post'}, // 获取登录用户
getMessageByUser: {path: '/getMessageByUser', method: 'post'}, // 查询用户消息列表
},
api: function(apiName, param, data){ // 封装axios请求
// 实例化axios
var apiList = this.apiList;
var HTTP = axios.create();
HTTP.defaults.baseURL = this.status.ctx,
HTTP.defaults.timeout = 30000;
HTTP.defaults.headers["mogenshixiong"] = "\\u771f\\u5e05";
var _httpLoading = false; // 加载中状态
var _httpTimeout;
// 请求拦截器
HTTP.interceptors.request.use(function(req){
_beforeReq(); return req;// 该返回的数据则是axios.then(res)中接收的数据
}, function(err){
_errorReq(); return Promise.reject(err); // 该返回的数据则是axios.catch(err)中接收的数据
});
// 响应拦截器
HTTP.interceptors.response.use(function(res){
_beforeRes(); return res; // 该返回的数据则是axios.then(res)中接收的数据
}, function(err){
_errorRes(); return Promise.reject(err); // 该返回的数据则是axios.catch(err)中接收的数据
});
// 返回请求Promise实例 (不考虑await,async兼容性问题的话可以修改)
return new Promise(function(resolve, reject) {
HTTP({
method: apiList[apiName].method,
url: _joinPath(apiList[apiName].path, param),
data: Qs.stringify(data)
}).then(function(res){
resolve(res.data);
}).catch(function (err) {
reject(err);
});
});
function _beforeReq(){
_httpTimeout = setTimeout(function(){
_httpLoading = true;
},300);//超过300ms请求,将显示loading }
function _errorReq(){
clearTimeout(_httpTimeout);
_httpLoading = false;
}
function _beforeRes(){
clearTimeout(_httpTimeout);
_httpLoading = false;
}
function _errorRes(){
clearTimeout(_httpTimeout);
_httpLoading = false;
}
function _joinPath(url, param){
return url +(url.indexOf('?') == -1?'?':'')+_serialize(param)
}
function _serialize(param){
var url = '';
for (var key in param) {
url += '&'+key+'='+param[key];
}
return url;
}
},
const: { // 常量定义
SUCCESS: 1,
ERROR: 0,
},
status:{ // 公共状态管理
ctx: 'http://127.0.0.1:8080', // baseURl
},
commonInit: function(){ // 公共初始化函数,执行与所有页面JS代码之前
console.log(m);
console.log( window.location.href );
},
data: {}, // 页面状态管理, 写在引用页面
controller: {}, // 页面业务逻辑方法, 写在引用页面
server: {}, // 页面实现方法, 写在引用页面
}
欢迎大家留言,探讨。