前言
一月份的时候,临近放假,拿到一个需求,新增一个产品,我一个前端对一个java后端,两个星期的开发时间。 因为大部分功能在别的产品都已经有了,基本都是简单处理一下拿过来,再添加一下额外需要的功能,比如选择出行国家等。前一天拿到文档看了下,搞清楚之后,第二天开工,基本一天就把功能做完了。这一天的大部分时间还是花在-找代码上。无他,实在是遗留的代码 不是很清晰。
因为系统比较旧,前后端也没有分离,jsp的,代码也很混乱,逻辑里面还有很多奇怪的注释,在这些上面做了很多无用功。 基本做好功能,联调测试,通过之后基本就OK了。
但是两个周的时间才用了两三天。还有十来天呢,怎么办呢,看着这些混乱的代码,本着造福别人,也为以后的方便,就想着,用模块重新组织一下吧。因为去年有过这方面经验,轻车熟路。所以,就有了后来的故事和今天的这篇文字。
改造前
改造前的代码大概是这个样子的:
<link href="../mobileSinglePlatform/css/miuiall.css" type="text/css" rel="stylesheet">
<link href="../mobileSinglePlatform/css/miuitraffic.css" type="text/css" rel="stylesheet">
<link href="../mobileSinglePlatform/css/mobiscroll.core-2.5.2.css" rel="stylesheet" type="text/css" />
<script src="../mobileSinglePlatform/js/jquery-1.8.2.min.js" type="text/javascript"></script>
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script src="../mobileSinglePlatform/js/common.js" type="text/javascript"></script>
<script src="../mobileSinglePlatform/js/dateUtil.js" type="text/javascript"></script>
<script src="../mobileSinglePlatform/js/ahsInsuranceForGroup_1.js" type="text/javascript"></script>
<script src="../mobileSinglePlatform/js/mobiscroll.core-2.5.2.js" type="text/javascript"></script>
<script src="../mobileSinglePlatform/js/mobiscroll.core-2.5.2-zh.js" type="text/javascript"></script>
<script src="../mobileSinglePlatform/js/mobiscroll.datetime-2.5.1.js" type="text/javascript"></script>
<script src="../mobileSinglePlatform/js/mobiscroll.datetime-2.5.1-zh.js" type="text/javascript"></script>
<script src="../mobileSinglePlatform/js/jquery.form.js" type="text/javascript"></script>
<script type="text/javascript" src="../mobileSinglePlatform/js/commonTools.js"></script>
<script type="text/javascript" src="../mobileSinglePlatform/js/getOpenId.js"></script>
<script type="text/javascript" src="../mobileSinglePlatform/js/wechatUtil.js"></script>
<script src="//www.pingan.com/app_js/sdc/prd/sdc9_m.js"> </script>
<script src="../mobileSinglePlatform/js/webtrends.js"></script>
<script type="text/javascript">
initWebtrends();
</script>
<c:if test="${not empty productDetail.specialPromise}">
<tr>
<td colspan="2">
</td>
</tr>
<tr>
<th width="60%" align="left">特别约定</th>
<th width="40%" align="right"> </th>
</tr>
<tr>
<td colspan="2">
<div id="specialInsurance" class="specialInsurance">
<div id="specialInsurancener">
<c:out value="${productDetail.specialPromise}"/>
</div>
</div>
<div id="readmore" class="specialInsurance" style="margin-top:3%;">
</div>
</td>
</tr>
</c:if>
<c:choose>
<c:when test="${not empty discountAmount}">
<tr>
<td colspan="2">
<!--#=保费-->
<div class="left fsize03 fwight" style="margin-top:20px;">标准保费 <del datetime="20150428"><font
id="fontColor"><span id="amount"><c:out value="${AMOUNT }"/></span>元/人</font></del></div>
</td>
</tr>
<tr>
<td colspan="2">
<!--#=保费优惠价-->
<div class="left fsize03 fwight" style="margin-top: 5px;color: #F00;padding: 5px 0px">优惠价 <span
id="standardAmount"><c:out value="${discountAmount }"/></span>元/人</div>
</td>
</tr>
</c:when>
不多贴代码了,大概就是这个样子的。这种情况的原因大概是:
1.起初的页面是后端人员写的,没有很好的组织各种资源。写到一定数量之后,各种逻辑已经耦合在一起,别的人接手之后,又不敢乱改,就按以前的做法复制粘贴,做好自己的那一块。久而久之,页面就越来越复杂,冗余也越来越多,形成了一个恶性循环。
2.网络环境不允许。使用公司标配的联想笔记本,标装之后,收到公司安全策略的限制,很多技术网站无法访问,查资料有时候只能看百度快照,有些同事只好用手机或者自带电脑来解决这个问题。至于 github,google,基本是不可能的。
3.没有代码规范。基本每个人都是按照自己的风格来,最后归并之后的代码就显得很混乱。
由于不能使用脚手架自动化工具,这种情景要做模块化,requireJs/seaJs 是比较好的选择。去年用过requireJs,这次就用一下seaJs.
由于项目中的样式文件实在太多太杂,时间上不允许我重新组织一遍,所以就只对逻辑代码做了模块化处理。
组织模块
要组织模块,首先要弄清楚相应的规则。最好的方式当然是看 seajs文档 了.
这里也简单介绍下几个常用的功能。
// 页面中包括的js
<script src="./js/seajs/2.3.0/sea.js" id="seajsnode" ></script>
<!--
加上 seajsnode 值,可以让 sea.js 直接获取到自身路径,而不需要通过其他机制去自动获取。
这对性能和稳定性会有一定提升,推荐默认都加上。
-->
<script src="./js/config-seajs.js" ></script>
<!--配置项 -->
<script type="text/javascript">
seajs.use('main');
/*
seajs.use 理论上只用于加载启动,不应该出现在 define 中的模块代码里。
在模块代码里需要异步加载其他模块时,推荐使用 require.async 方法。
*/
</script>
再看一下配置信息:
seajs.config({
base:"./js/",
paths: { //当目录比较深,或需要跨目录调用模块时,可以使用 paths 来简化书写。
"seajs": "seajs/2.3.0/sea.js"
},
alias:{ // 设置别名,方便调用 , 当模块标识很长时,可以使用 alias 来简化。
"jquery" : "lib/jquery/1.10.0/jquery.min.js",
'Hello':'mod/mod4.js',
},
map: [
[".js",".js?1.0"]
],
debug:true //值为 true 时,加载器不会删除动态插入的 script 标签。插件也可以根据 debug 配置,来决策 log 等信息的输出。
});
然后是页面入口:
//main.js
/*
define define(factory)
define 接受 factory 参数,factory 可以是一个函数,也可以是一个对象或字符串。
factory 为对象、字符串时,表示模块的接口就是该对象、字符串。比如可以如下定义一个 JSON 数据模块:
define({ "foo": "bar" });
也可以通过字符串定义模板模块:
define('I am a template. My name is {{name}}.');
factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory 方法在执行时,默认会传入三个参数:require、exports 和 module:
define(function(require, exports, module) {
// 模块代码
});
*/
define(function (require, exports, module) {
var $ = require('jquery');
console.log($);
require('mod1');
var Hello = require('Hello');
Hello.init();
// other code...
});
看一下模块内的代码:
//mod1.js
define(function (require, exports, module) {
console.log('mod1加载完毕');
});
//mod4.js
define('Hello',function(require,exports, module) {
var Hello = {
sayHello:function(){
console.log('hello');
}
}
module.exports = Hello;
});
打开页面控制台,就会看到输出的信息:
说明我们的模块已经被成功的被加载了。
当然 实际的工作中还要用到各种插件,这就需要知道如何改造现有文件为 CMD 模块
这些在文档中都能找到。
以上简单介绍了使用seajs 组织模块的方法。
当然,模块写完之后呢,我们还需要相应的构建工具。
玉伯说:
如果使用 Sea.js,强烈推荐采用配套的构建工具来压缩、合并代码。如果不这么做,可能会带来不少额外的工作甚至隐患。
如果不合并代码,也能运行,你会看到你的插件代码都会以async的方式插入到页面的头部。而且需要你手动处理依赖关系,也产生了额外的请求,不是很友好。如下图:
所以,为了避免意外的发生,也为了减少请求数,应该合并模块。
我们来看一个实际的例子-支付宝的登陆页面。
在网页支付宝收银台中的运用
![clipboard.png]
很直观的就能看到插模块的合并,这个合并的工作就是构建工具的功劳了。
我们也来实现一下。
先看效果吧,执行模块合并之后,入口文件可以是这样的:
这样就实现了模块的打包合并。
我这里使用了gulp来实现这一步, 代码如下:
//seajs合并模式
gulp.task("seajs", function () {
return merge(
gulp.src(src + '/js/!(lib)/**/*.js', {base: src + '/js'})
.pipe(transport())
.pipe(concat({
base: src + '/js'
}))
.pipe(replace({
patterns: replace_patterns
}))
.pipe(gulp.dest(dist + '/js')),
gulp.src([src + '/js/lib/**/*.js', src + '/js/common.js'], {
base: src + '/js'
})
.pipe(replace({
patterns: replace_patterns
}))
.pipe(gulp.dest(dist + '/js'))
);
});
使用gulp提取模块有其他更详细的教程,这里提供一个我认为比较好的:
那个支付宝的登陆页 这里给出完整代码,给大家观摩:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1"/>
<meta name="renderer" content="webkit"/>
<title>支付宝快捷收银台</title>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta name="format-detection" content="telephone=no,email=no"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0"/>
<link rel="apple-touch-icon" href="https://i.alipayobjects.com/i/ecmng/png/201406/2qBuceUYiL.png" />
<link rel="apple-touch-icon-precomposed" href="https://i.alipayobjects.com/i/ecmng/png/201406/2qBuceUYiL.png" />
<!-- CMS:安全支付客户端网关/common/tracker.vm开始:common/tracker.vm -->
<!-- CMS:安全支付客户端网关/common/tracker.vm结束:common/tracker.vm --><script charset="utf-8" src="https://as.alipayobjects.com:443/g/snake/h5cashier/1.0.5/h5cashier.js"></script>
<link rel="stylesheet" type="text/css" href="https://as.alipayobjects.com:443/g/snake/h5cashier/1.0.5/h5cashier.css" media="all" />
<script charset="utf-8" id="seajsnode" src="https://a.alipayobjects.com:443/??seajs/seajs/2.2.0/sea.js,seajs/seajs-combo/1.0.0/seajs-combo.js"></script>
<script>
seajs.config({
alias: {
'$': 'gallery/zepto/1.0.2/zepto',
'validator': 'arale/validator/0.9.7/validator',
'widget': 'arale/widget/1.1.1/widget',
'base': 'arale/base/1.1.1/base',
'class': 'arale/class/1.1.0/class',
'events': 'arale/events/1.1.0/events',
'wapcashier': 'mobileclientgw/wapcashier/1.1.7/wapcashier'
},
vars: {
locale: 'zh-cn'
}
});
</script>
</head>
<body>
<div class="J-msg-mask am-msg-mask" style="display:none"></div>
<div class="J-msg-box am-msg-box" style="display:none">
<div class="am-msg-box-content">
<p class="J-msg-text"></p>
<button class="J-msg-cancel am-button am-button-blue" type="button">知道了</button>
</div>
</div>
<div class="J-loading am-loading"><div class="am-loading-text">加载中...</div></div>
<!-- CMS:安全支付客户端网关/common/notice.vm开始:common/notice.vm --><!-- CMS:安全支付客户端网关/common/notice.vm结束:common/notice.vm -->
<!-- cashierLoginNew.vm -->
<!-- v5_need_login_new -->
<script>window.Tracker && Tracker.click('v5_need_login_new')</script>
<header class="am-header">
<h1>
<span class="title-main" data-title="登录支付宝">登录支付宝</span> </h1>
<a href="#" class="J-back J-header-back am-header-reverse am-header-reverse-icon" seed="v5_need_login_new-back"><i class="icon icon-arrow-back"></i><span>返回</span></a>
</header>
<noscript><h1 style="color:red">您的浏览器不支持JavaScript,请更换浏览器或开启JavaScript设置!</h1></noscript>
<style>
h5 {
overflow: hidden;
}
.am-content h5.am-ft-mb-20 {
margin-bottom: 20px;
}
</style>
<div class="am-content">
<form id="cashier" action="https://mclient.alipay.com/h5/loginIdPwdLogin.htm?awid=RZ117V8UyX8dVXb9l8WaAkSdN6nF7kmobileclientgwRZ11" method="post">
<!-- 禁止浏览器自动填充账户名密码 -->
<input style="display:none" type="text" name="fakeusernameremembered"/>
<input style="display:none" type="password" name="fakepasswordremembered"/>
<!-- /禁止浏览器自动填充账户名密码 -->
<input type="hidden" name="_form_token" value="b63232f9568b71d0ad1425ca684e67f9b546a51c877e484f987868163c47e6f2RZ11"/>
<input type="hidden" name="params" value="{"server_param":"c2hhcmVkX3RhaXI9dHJ1ZTtiaXpfdHlwZT1tZXJjaGFudDthY3Rpb249cGFyc2VyTG9nb25JZDs%3D","shared_tair":"true"}" />
<input type="hidden" name="session" value="RZ11Pu0jYCjXnsRvOUWIWJNRmBh2BamobilecashierRZ11" />
<input type="hidden" name="check_pay_pwd" value="true" />
<div class="am-list">
<div class="J-inputClear am-list-item am-list-item-form am-flexbox">
<label for="logon_id">账户 </label>
<div class="am-flexbox-item">
<input id="logon_id" name="logon_id" type="text" maxlength="100" placeholder="支付宝账户" value="" autocomplete="off" autofocus="autofocus" />
</div>
</div>
<div class="J-inputClear am-list-item am-list-item-form am-flexbox">
<label for="pwd">密码 </label>
<div class="am-flexbox-item">
<input type="password" class="J-pwd" id="pwd_unencrypt" name="pwd_unencrypt" maxlength="100" placeholder="是支付密码,不是登录密码" autocomplete="off" />
<input type="hidden" id="pwd" name="pwd" class="J-encryptpwd" />
</div>
</div>
</div>
<div class="am-section">
<div class="am-ft-pb-10">
<button type="submit" class="am-button am-button-blue" seed="v5_need_login_new-submit">下一步</button>
</div>
<h5 class="am-ft-gray am-ft-mb-20">
<a class="fn-right" href="https://d.alipay.com/i/index.htm?pageSkin=skin-h5cashier&iframeSrc=alipays%3A%2F%2Fplatformapi%2FstartApp%3FappId%3D20000013%26pwdType%3DordinaryPassword" seed="v5_need_login_new-forget-pwd">忘记密码</a>
</h5>
</div>
</form>
</div>
<script type="text/javascript">
seajs.use(['$', 'wapcashier', 'validator', 'widget', 'base', 'class', 'events'],function($, wapcashier, Validator){
//刷新图片校验码
var checkCode = $('.J-check-code');
checkCode.on('click',function(e){
var el = $(e.target);
el.attr('src', el.attr('src') + '&s=' + Math.random())
});
//表单校验
var validator = new Validator({
element: $('form#cashier'),
autoSubmit: false,
stopOnError: true,
autoFocus: false,
onFormValidated: function(err, results, form) {
if(!err) {
form[0].submit();
} else {
Zepto.each(results, function(key, value){
if(value[1] != null) return errorMessages = value[1];
})
showMsg(errorMessages);
}
},
triggerType: 'submit',
failSilently: true
});
validator.addItem({
element: '#logon_id',
required: true,
errormessageRequired: '支付宝账户不能为空',
display: '支付宝账户',
onItemValidated: function(error, message, elem) {
if(error) window.Tracker&&Tracker.click('v5_need_login_new-' + elem.attr('name') + '-' + error);
}
});
var isInputEvent = "oninput" in document ? true : false;
var inputEvent = isInputEvent ? "input" : 'keyup';
//RSA
try {
var dbits;var canary=0xdeadbeefcafe;var j_lm=((canary&0xffffff)==0xefcafe);function BigInteger(a,b,c){if(a!=null)
if("number"==typeof a)this.fromNumber(a,b,c);else if(b==null&&"string"!=typeof a)this.fromString(a,256);else this.fromString(a,b);}
function nbi(){return new BigInteger(null);}
function am1(i,x,w,j,c,n){while(--n>=0){var v=x*this[i++]+w[j]+c;c=Math.floor(v/0x4000000);w[j++]=v&0x3ffffff;}
return c;}
function am2(i,x,w,j,c,n){var xl=x&0x7fff,xh=x>>15;while(--n>=0){var l=this[i]&0x7fff;var h=this[i++]>>15;var m=xh*l+h*xl;l=xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);c=(l>>>30)+(m>>>15)+xh*h+(c>>>30);w[j++]=l&0x3fffffff;}
return c;}
function am3(i,x,w,j,c,n){var xl=x&0x3fff,xh=x>>14;while(--n>=0){var l=this[i]&0x3fff;var h=this[i++]>>14;var m=xh*l+h*xl;l=xl*l+((m&0x3fff)<<14)+w[j]+c;c=(l>>28)+(m>>14)+xh*h;w[j++]=l&0xfffffff;}
return c;}
if(j_lm&&(navigator.appName=="Microsoft Internet Explorer")){BigInteger.prototype.am=am2;dbits=30;}
else if(j_lm&&(navigator.appName!="Netscape")){BigInteger.prototype.am=am1;dbits=26;}
else{BigInteger.prototype.am=am3;dbits=28;}
BigInteger.prototype.DB=dbits;BigInteger.prototype.DM=((1<<dbits)-1);BigInteger.prototype.DV=(1<<dbits);var BI_FP=52;BigInteger.prototype.FV=Math.pow(2,BI_FP);BigInteger.prototype.F1=BI_FP-dbits;BigInteger.prototype.F2=2*dbits-BI_FP;var BI_RM="0123456789abcdefghijklmnopqrstuvwxyz";var BI_RC=new Array();var rr,vv;rr="0".charCodeAt(0);for(vv=0;vv<=9;++vv)BI_RC[rr++]=vv;rr="a".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;rr="A".charCodeAt(0);for(vv=10;vv<36;++vv)BI_RC[rr++]=vv;function int2char(n){return BI_RM.charAt(n);}
function intAt(s,i){var c=BI_RC[s.charCodeAt(i)];return(c==null)?-1:c;}
function bnpCopyTo(r){for(var i=this.t-1;i>=0;--i)r[i]=this[i];r.t=this.t;r.s=this.s;}
function bnpFromInt(x){this.t=1;this.s=(x<0)?-1:0;if(x>0)this[0]=x;else if(x<-1)this[0]=x+this.DV;else this.t=0;}
function nbv(i){var r=nbi();r.fromInt(i);return r;}
function bnpFromString(s,b){var k;if(b==16)k=4;else if(b==8)k=3;else if(b==256)k=8;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else{this.fromRadix(s,b);return;}
this.t=0;this.s=0;var i=s.length,mi=false,sh=0;while(--i>=0){var x=(k==8)?s[i]&0xff:intAt(s,i);if(x<0){if(s.charAt(i)=="-")mi=true;continue;}
mi=false;if(sh==0)
this[this.t++]=x;else if(sh+k>this.DB){this[this.t-1]|=(x&((1<<(this.DB-sh))-1))<<sh;this[this.t++]=(x>>(this.DB-sh));}
else
this[this.t-1]|=x<<sh;sh+=k;if(sh>=this.DB)sh-=this.DB;}
if(k==8&&(s[0]&0x80)!=0){this.s=-1;if(sh>0)this[this.t-1]|=((1<<(this.DB-sh))-1)<<sh;}
this.clamp();if(mi)BigInteger.ZERO.subTo(this,this);}
function bnpClamp(){var c=this.s&this.DM;while(this.t>0&&this[this.t-1]==c)--this.t;}
function bnToString(b){if(this.s<0)return"-"+this.negate().toString(b);var k;if(b==16)k=4;else if(b==8)k=3;else if(b==2)k=1;else if(b==32)k=5;else if(b==4)k=2;else return this.toRadix(b);var km=(1<<k)-1,d,m=false,r="",i=this.t;var p=this.DB-(i*this.DB)%k;if(i-->0){if(p<this.DB&&(d=this[i]>>p)>0){m=true;r=int2char(d);}
while(i>=0){if(p<k){d=(this[i]&((1<<p)-1))<<(k-p);d|=this[--i]>>(p+=this.DB-k);}
else{d=(this[i]>>(p-=k))&km;if(p<=0){p+=this.DB;--i;}}
if(d>0)m=true;if(m)r+=int2char(d);}}
return m?r:"0";}
function bnNegate(){var r=nbi();BigInteger.ZERO.subTo(this,r);return r;}
function bnAbs(){return(this.s<0)?this.negate():this;}
function bnCompareTo(a){var r=this.s-a.s;if(r!=0)return r;var i=this.t;r=i-a.t;if(r!=0)return(this.s<0)?-r:r;while(--i>=0)if((r=this[i]-a[i])!=0)return r;return 0;}
function nbits(x){var r=1,t;if((t=x>>>16)!=0){x=t;r+=16;}
if((t=x>>8)!=0){x=t;r+=8;}
if((t=x>>4)!=0){x=t;r+=4;}
if((t=x>>2)!=0){x=t;r+=2;}
if((t=x>>1)!=0){x=t;r+=1;}
return r;}
function bnBitLength(){if(this.t<=0)return 0;return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));}
function bnpDLShiftTo(n,r){var i;for(i=this.t-1;i>=0;--i)r[i+n]=this[i];for(i=n-1;i>=0;--i)r[i]=0;r.t=this.t+n;r.s=this.s;}
function bnpDRShiftTo(n,r){for(var i=n;i<this.t;++i)r[i-n]=this[i];r.t=Math.max(this.t-n,0);r.s=this.s;}
function bnpLShiftTo(n,r){var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<cbs)-1;var ds=Math.floor(n/this.DB),c=(this.s<<bs)&this.DM,i;for(i=this.t-1;i>=0;--i){r[i+ds+1]=(this[i]>>cbs)|c;c=(this[i]&bm)<<bs;}
for(i=ds-1;i>=0;--i)r[i]=0;r[ds]=c;r.t=this.t+ds+1;r.s=this.s;r.clamp();}
function bnpRShiftTo(n,r){r.s=this.s;var ds=Math.floor(n/this.DB);if(ds>=this.t){r.t=0;return;}
var bs=n%this.DB;var cbs=this.DB-bs;var bm=(1<<bs)-1;r[0]=this[ds]>>bs;for(var i=ds+1;i<this.t;++i){r[i-ds-1]|=(this[i]&bm)<<cbs;r[i-ds]=this[i]>>bs;}
if(bs>0)r[this.t-ds-1]|=(this.s&bm)<<cbs;r.t=this.t-ds;r.clamp();}
function bnpSubTo(a,r){var i=0,c=0,m=Math.min(a.t,this.t);while(i<m){c+=this[i]-a[i];r[i++]=c&this.DM;c>>=this.DB;}
if(a.t<this.t){c-=a.s;while(i<this.t){c+=this[i];r[i++]=c&this.DM;c>>=this.DB;}
c+=this.s;}
else{c+=this.s;while(i<a.t){c-=a[i];r[i++]=c&this.DM;c>>=this.DB;}
c-=a.s;}
r.s=(c<0)?-1:0;if(c<-1)r[i++]=this.DV+c;else if(c>0)r[i++]=c;r.t=i;r.clamp();}
function bnpMultiplyTo(a,r){var x=this.abs(),y=a.abs();var i=x.t;r.t=i+y.t;while(--i>=0)r[i]=0;for(i=0;i<y.t;++i)r[i+x.t]=x.am(0,y[i],r,i,0,x.t);r.s=0;r.clamp();if(this.s!=a.s)BigInteger.ZERO.subTo(r,r);}
function bnpSquareTo(r){var x=this.abs();var i=r.t=2*x.t;while(--i>=0)r[i]=0;for(i=0;i<x.t-1;++i){var c=x.am(i,x[i],r,2*i,0,1);if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1))>=x.DV){r[i+x.t]-=x.DV;r[i+x.t+1]=1;}}
if(r.t>0)r[r.t-1]+=x.am(i,x[i],r,2*i,0,1);r.s=0;r.clamp();}
function bnpDivRemTo(m,q,r){var pm=m.abs();if(pm.t<=0)return;var pt=this.abs();if(pt.t<pm.t){if(q!=null)q.fromInt(0);if(r!=null)this.copyTo(r);return;}
if(r==null)r=nbi();var y=nbi(),ts=this.s,ms=m.s;var nsh=this.DB-nbits(pm[pm.t-1]);if(nsh>0){pm.lShiftTo(nsh,y);pt.lShiftTo(nsh,r);}
else{pm.copyTo(y);pt.copyTo(r);}
var ys=y.t;var y0=y[ys-1];if(y0==0)return;var yt=y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);var d1=this.FV/yt,d2=(1<<this.F1)/yt,e=1<<this.F2;var i=r.t,j=i-ys,t=(q==null)?nbi():q;y.dlShiftTo(j,t);if(r.compareTo(t)>=0){r[r.t++]=1;r.subTo(t,r);}
BigInteger.ONE.dlShiftTo(ys,t);t.subTo(y,y);while(y.t<ys)y[y.t++]=0;while(--j>=0){var qd=(r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);if((r[i]+=y.am(0,qd,r,j,0,ys))<qd){y.dlShiftTo(j,t);r.subTo(t,r);while(r[i]<--qd)r.subTo(t,r);}}
if(q!=null){r.drShiftTo(ys,q);if(ts!=ms)BigInteger.ZERO.subTo(q,q);}
r.t=ys;r.clamp();if(nsh>0)r.rShiftTo(nsh,r);if(ts<0)BigInteger.ZERO.subTo(r,r);}
function bnMod(a){var r=nbi();this.abs().divRemTo(a,null,r);if(this.s<0&&r.compareTo(BigInteger.ZERO)>0)a.subTo(r,r);return r;}
function Classic(m){this.m=m;}
function cConvert(x){if(x.s<0||x.compareTo(this.m)>=0)return x.mod(this.m);else return x;}
function cRevert(x){return x;}
function cReduce(x){x.divRemTo(this.m,null,x);}
function cMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r);}
function cSqrTo(x,r){x.squareTo(r);this.reduce(r);}
Classic.prototype.convert=cConvert;Classic.prototype.revert=cRevert;Classic.prototype.reduce=cReduce;Classic.prototype.mulTo=cMulTo;Classic.prototype.sqrTo=cSqrTo;function bnpInvDigit(){if(this.t<1)return 0;var x=this[0];if((x&1)==0)return 0;var y=x&3;y=(y*(2-(x&0xf)*y))&0xf;y=(y*(2-(x&0xff)*y))&0xff;y=(y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;y=(y*(2-x*y%this.DV))%this.DV;return(y>0)?this.DV-y:-y;}
function Montgomery(m){this.m=m;this.mp=m.invDigit();this.mpl=this.mp&0x7fff;this.mph=this.mp>>15;this.um=(1<<(m.DB-15))-1;this.mt2=2*m.t;}
function montConvert(x){var r=nbi();x.abs().dlShiftTo(this.m.t,r);r.divRemTo(this.m,null,r);if(x.s<0&&r.compareTo(BigInteger.ZERO)>0)this.m.subTo(r,r);return r;}
function montRevert(x){var r=nbi();x.copyTo(r);this.reduce(r);return r;}
function montReduce(x){while(x.t<=this.mt2)
x[x.t++]=0;for(var i=0;i<this.m.t;++i){var j=x[i]&0x7fff;var u0=(j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;j=i+this.m.t;x[j]+=this.m.am(0,u0,x,i,0,this.m.t);while(x[j]>=x.DV){x[j]-=x.DV;x[++j]++;}}
x.clamp();x.drShiftTo(this.m.t,x);if(x.compareTo(this.m)>=0)x.subTo(this.m,x);}
function montSqrTo(x,r){x.squareTo(r);this.reduce(r);}
function montMulTo(x,y,r){x.multiplyTo(y,r);this.reduce(r);}
Montgomery.prototype.convert=montConvert;Montgomery.prototype.revert=montRevert;Montgomery.prototype.reduce=montReduce;Montgomery.prototype.mulTo=montMulTo;Montgomery.prototype.sqrTo=montSqrTo;function bnpIsEven(){return((this.t>0)?(this[0]&1):this.s)==0;}
function bnpExp(e,z){if(e>0xffffffff||e<1)return BigInteger.ONE;var r=nbi(),r2=nbi(),g=z.convert(this),i=nbits(e)-1;g.copyTo(r);while(--i>=0){z.sqrTo(r,r2);if((e&(1<<i))>0)z.mulTo(r2,g,r);else{var t=r;r=r2;r2=t;}}
return z.revert(r);}
function bnModPowInt(e,m){var z;if(e<256||m.isEven())z=new Classic(m);else z=new Montgomery(m);return this.exp(e,z);}
BigInteger.prototype.copyTo=bnpCopyTo;BigInteger.prototype.fromInt=bnpFromInt;BigInteger.prototype.fromString=bnpFromString;BigInteger.prototype.clamp=bnpClamp;BigInteger.prototype.dlShiftTo=bnpDLShiftTo;BigInteger.prototype.drShiftTo=bnpDRShiftTo;BigInteger.prototype.lShiftTo=bnpLShiftTo;BigInteger.prototype.rShiftTo=bnpRShiftTo;BigInteger.prototype.subTo=bnpSubTo;BigInteger.prototype.multiplyTo=bnpMultiplyTo;BigInteger.prototype.squareTo=bnpSquareTo;BigInteger.prototype.divRemTo=bnpDivRemTo;BigInteger.prototype.invDigit=bnpInvDigit;BigInteger.prototype.isEven=bnpIsEven;BigInteger.prototype.exp=bnpExp;BigInteger.prototype.toString=bnToString;BigInteger.prototype.negate=bnNegate;BigInteger.prototype.abs=bnAbs;BigInteger.prototype.compareTo=bnCompareTo;BigInteger.prototype.bitLength=bnBitLength;BigInteger.prototype.mod=bnMod;BigInteger.prototype.modPowInt=bnModPowInt;BigInteger.ZERO=nbv(0);BigInteger.ONE=nbv(1);function Arcfour(){this.i=0;this.j=0;this.S=new Array();}
function ARC4init(key){var i,j,t;for(i=0;i<256;++i)
this.S[i]=i;j=0;for(i=0;i<256;++i){j=(j+this.S[i]+key[i%key.length])&255;t=this.S[i];this.S[i]=this.S[j];this.S[j]=t;}
this.i=0;this.j=0;}
function ARC4next(){var t;this.i=(this.i+1)&255;this.j=(this.j+this.S[this.i])&255;t=this.S[this.i];this.S[this.i]=this.S[this.j];this.S[this.j]=t;return this.S[(t+this.S[this.i])&255];}
Arcfour.prototype.init=ARC4init;Arcfour.prototype.next=ARC4next;function prng_newstate(){return new Arcfour();}
var rng_psize=256;var rng_state;var rng_pool;var rng_pptr;function rng_seed_int(x){rng_pool[rng_pptr++]^=x&255;rng_pool[rng_pptr++]^=(x>>8)&255;rng_pool[rng_pptr++]^=(x>>16)&255;rng_pool[rng_pptr++]^=(x>>24)&255;if(rng_pptr>=rng_psize)rng_pptr-=rng_psize;}
function rng_seed_time(){rng_seed_int(new Date().getTime());}
if(rng_pool==null){rng_pool=new Array();rng_pptr=0;var t;if(window.crypto&&window.crypto.getRandomValues){var ua=new Uint8Array(32);window.crypto.getRandomValues(ua);for(t=0;t<32;++t)
rng_pool[rng_pptr++]=ua[t];}
if(navigator.appName=="Netscape"&&navigator.appVersion<"5"&&window.crypto){var z=window.crypto.random(32);for(t=0;t<z.length;++t)
rng_pool[rng_pptr++]=z.charCodeAt(t)&255;}
while(rng_pptr<rng_psize){t=Math.floor(65536*Math.random());rng_pool[rng_pptr++]=t>>>8;rng_pool[rng_pptr++]=t&255;}
rng_pptr=0;rng_seed_time();}
function rng_get_byte(){if(rng_state==null){rng_seed_time();rng_state=prng_newstate();rng_state.init(rng_pool);for(rng_pptr=0;rng_pptr<rng_pool.length;++rng_pptr)
rng_pool[rng_pptr]=0;rng_pptr=0;}
return rng_state.next();}
function rng_get_bytes(ba){var i;for(i=0;i<ba.length;++i)ba[i]=rng_get_byte();}
function SecureRandom(){}
SecureRandom.prototype.nextBytes=rng_get_bytes;function parseBigInt(str,r){return new BigInteger(str,r);}
function linebrk(s,n){var ret="";var i=0;while(i+n<s.length){ret+=s.substring(i,i+n)+"\n";i+=n;}
return ret+s.substring(i,s.length);}
function byte2Hex(b){if(b<0x10)
return"0"+b.toString(16);else
return b.toString(16);}
function pkcs1pad2(s,n){if(n<s.length+11){alert("Message too long for RSA");return null;}
var ba=new Array();var i=s.length-1;while(i>=0&&n>0){var c=s.charCodeAt(i--);if(c<128){ba[--n]=c;}
else if((c>127)&&(c<2048)){ba[--n]=(c&63)|128;ba[--n]=(c>>6)|192;}
else{ba[--n]=(c&63)|128;ba[--n]=((c>>6)&63)|128;ba[--n]=(c>>12)|224;}}
ba[--n]=0;var rng=new SecureRandom();var x=new Array();while(n>2){x[0]=0;while(x[0]==0)rng.nextBytes(x);ba[--n]=x[0];}
ba[--n]=2;ba[--n]=0;return new BigInteger(ba);}
function RSAKey(){this.n=null;this.e=0;this.d=null;this.p=null;this.q=null;this.dmp1=null;this.dmq1=null;this.coeff=null;}
function RSASetPublic(N,E){if(N!=null&&E!=null&&N.length>0&&E.length>0){this.n=parseBigInt(N,16);this.e=parseInt(E,16);}
else
alert("Invalid RSA public key");}
function RSADoPublic(x){return x.modPowInt(this.e,this.n);}
function RSAEncrypt(text){var m=pkcs1pad2(text,(this.n.bitLength()+7)>>3);if(m==null)return null;var c=this.doPublic(m);if(c==null)return null;var h=c.toString(16);if((h.length&1)==0)return h;else return"0"+h;}
RSAKey.prototype.doPublic=RSADoPublic;RSAKey.prototype.setPublic=RSASetPublic;RSAKey.prototype.encrypt=RSAEncrypt;var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var b64padchar="=";function hex2b64(h){var i;var c;var ret="";for(i=0;i+3<=h.length;i+=3){c=parseInt(h.substring(i,i+3),16);ret+=b64map.charAt(c>>6)+b64map.charAt(c&63);}
if(i+1==h.length){c=parseInt(h.substring(i,i+1),16);ret+=b64map.charAt(c<<2);}
else if(i+2==h.length){c=parseInt(h.substring(i,i+2),16);ret+=b64map.charAt(c>>2)+b64map.charAt((c&3)<<4);}
while((ret.length&3)>0)ret+=b64padchar;return ret;}
var rsa_n = 'B98DC71833036E62C92BF6ABA5DFDDABBD44E52932CAE2026ED2A71C22E7681644A3233276F2EB7B29EC56CB720A3B8A8BFAEEA3E5E00D03E4E82203F676EBF5';
var rsa_e = '10001';
var encrypt = function(data) {
var setRSA = new RSAKey();
setRSA.setPublic(rsa_n, rsa_e);
var res = setRSA.encrypt(data);
if(res) {
return linebrk(hex2b64(res), 64);
} else {
return '*';
}
}
var pwd = $('.J-pwd');
var encryptpwd = $('.J-encryptpwd');
var isPaste = false;
var clean = function () {
pwd.val('');
encryptpwd.val('');
}
clean();
var setRange = function (el) {
el.setSelectionRange(parseInt(el.value.length + 1), parseInt(el.value.length + 1))
}
pwd.on('focus',function(e){
var el = e.target;
setRange(el);
});
pwd.on('keydown',function(e){
var el = e.target;
if (e.which === 8 || e.which === 46) clean();
setRange(el);
});
pwd.on('keyup',function(e){
var el = e.target;
setRange(el);
});
pwd.on('paste',function(e){
isPaste = true;
});
//默认清空加密(浏览器点返回会保留之前的值)
encryptpwd.val('');
pwd.on(inputEvent,function(e){
var el = e.target;
if (isPaste) clean();
isPaste = false;
setRange(el);
var currentPW = el.value.split('*').slice(-1).toString();
var encryptPW = encryptpwd[0].value;
//删除(触发input事件,未获取删除keycode)
if(currentPW.length === 0) {
encryptpwd[0].value = encryptpwd[0].value.split(',').slice(0, el.value.length).toString();
} else {
//新增
for (var i=0;i < currentPW.length;i++) {
var outkey = encrypt(currentPW[i]);
if(encryptpwd.val() === ''){
encryptpwd.val(outkey);
} else {
encryptpwd[0].value += ',' + outkey;
}
}
el.value = el.value.replace(/\S/g,"*")
}
});
}catch(e){}
validator.addItem({
element: '#pwd',
required: true,
errormessageRequired: '请填写支付密码',
display: '支付密码',
onItemValidate: function(error, message, elem) {
if($('.J-encryptpwd').val() === '') {
$('.J-encryptpwd').val($('.J-pwd').val());
}
},
onItemValidated: function(error, message, elem) {
if($('.J-encryptpwd').val() === '') {
$('.J-encryptpwd').val($('.J-pwd').val());
}
if(error) {
$('.J-pwd').val('');
$('.J-encryptpwd').val('');
}
if(error) window.Tracker&&Tracker.click('v5_need_login_new-' + elem.attr('name') + '-' + error);
}
});
});
$(function(){
$('.J-back').on('click',function(e){
window.history.back();
e.preventDefault();
});
$('.J-loading').addClass('fn-hide');
$('.J-open-protocol').on('click',function(e){
var el = $(this);
Zepto.dialog.show({
message: '<div style="height: 280px;-webkit-overflow-scrolling:touch;overflow:auto;"><iframe style="height: 280px;width: 100%;overflow: auto;" src="' + el.attr('href') + '" frameborder="0" scrolling="auto" allowTransparency="true"></iframe></div>',
buttons: '确定',
complete: function () {
Zepto.dialog.hide();
}
});
e.preventDefault();
});
// fix dialog连续闪动的问题
Zepto.dialog.hide = function() {
$('body').find('.am-dialog-mask').remove();
$('body').find('.am-dialog-box').remove();
}
});
</script>
<script type="text/javascript">
var form_tk = "b63232f9568b71d0ad1425ca684e67f9b546a51c877e484f987868163c47e6f2RZ11";
var json_ua;
</script>
<script src="https://rds.alipay.com/ua_mobilecashier_login.js?t=2017081515"></script>
<script>
(function (w, d, t) {
var s = d.createElement(t), m = d.getElementsByTagName(t)[0];
s.async = 1;
s.src = "https://g.alicdn.com/sd/pointman/js/pt2.js?f=m&_=" + Math.floor((new Date()).getTime() / 36e5);
m.parentNode.insertBefore(s, m);
w._pointman_q = w._pointman_q || [];
_pointman_q.push(["um", function (um) {
um.init({
timeout: 3000,
token:'P14c3df62cee8d4bb94634ae243d1ad82',
userid: '',
serviceLocation: "cn",
appName: 'mobileclientgw'
});
}]);
})(window, document, "script");
</script>
<footer>
<div class="alipay-logo"></div>
<div id="ServerNum">mobileclientgw-30-5</div>
</footer>
<!-- CMS:安全支付客户端网关/common/footer.vm开始:mobileclientgw/common/footer.vm --> <script type="text/javascript">
if(navigator.userAgent.indexOf('sdk') > 0) {$('input[data-format]').attr('data-format', '100')}
//12.03下线
if(window.Zepto && Zepto.dialog && $('.J-header-return') != -1){
Zepto.dialog.hide = function() {
$('body').find('.am-dialog-mask').animate({
opacity: 0
}, 400, 'ease-out', function(){
$(this).css('display', 'none');
});
$('body').find('.am-dialog-box').animate({
opacity: 0
}, 400, 'ease-out', function(){
$(this).css('display', 'none');
});
window.setTimeout(function(){
$('body').find('.am-dialog-mask').remove();
$('body').find('.am-dialog-box').remove();
},1000);
}
}
</script><!-- CMS:安全支付客户端网关/common/footer.vm结束:mobileclientgw/common/footer.vm --></body>
</html>
改造后
改造到最后呢,页面逻辑清爽多了,再有新的模块,写好之后别人直接调用就可以了,write once, run everywhere .
define(function(require) {
var $ = require("jquery"),
$body = $(document.body),
setDate = require("components/setDate"),
selectCity = require("components/selectCity"),
commonTools = require("tools/commonTools"),
FastClick = require("fastClick"),
myLayer = require("myLayer");
//内部统计
var webTrends = require("webTrends");
webTrends.init();
// 百度统计
var baiduTrends = require("baiduTrends");
baiduTrends.init();
// 初始化时间选择
setDate.dateTime.init();
// 选择目的地
selectCity.init();
var actionList = {
'applyInsurance' :function(){
//xxx
}
});
完整的代码就不展示了,都是一些逻辑,没什么好看的。
最后
花了大概一个周的时间初步重构了一下项目代码,改得很粗糙,只是做了一些大概的拆分,毕竟遗留的代码太多,需要和小伙伴一起做这个事。
由于公司标装的电脑用不了npm那些,最后的一步是我在mac上弄好,然后拷贝到公司电脑上,中间还出了很多问题,不过好在能跑了,至于最后能不能用起来..只能说,努力吧。
seajs 可以说是上个年代的产物了,不过在一些老旧项目中,依然可以发挥光和热。
写到这里差不多也要结束了,我呢,也算完成了给自己定的一个小目标,不算多大的贡献,只当给自己一个交代。
以上大概就是全部内容,希望给大家带来一些启发和帮助,谢谢。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。