传统前端项目中,如何管理代码。

203 阅读3分钟

在前端的工作业务场景中,不可避免的需要使用传统的方式编写业务代码,或者重构优化之前的项目的代码。或者有些前端小伙伴(包括我),因为各种原因,大部分的工作还是以传统的方式进行。

本文也在进行一种尝试或者说探索,希望传统的开发方式,更加的规范化。

先看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: {}, // 页面实现方法, 写在引用页面
}

欢迎大家留言,探讨。