`
Mossad
  • 浏览: 82161 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

小米10月15日抢购前端代码分析

 
阅读更多

首先感谢huangzhir同学的小米抢购前端代码分析,我分析的代码也是从他那里拿的,这篇文章只想为自己留个备份,大家有兴趣也可以看一看,可能有些东西对你有所帮助也说不定。直接贴代码:

var isRollStatus = false, isPhone = false, isBox = false;
(function() {
	m = {
		arrelems : [],//没用到
		ready : null,
		doms : function() {
			var _this = this;
			var isReady = false;
			var readyList = [];
			var timer;
			_this.ready = function(fn) {
				if (isReady) {
					fn.call(document);//直接执行,这样就readyList没用了,所以readyList虽然是数组,但其实只会有一个函数元素。
				} else {
					readyList.push(function() {
						return fn.call(this);//执行的时候this指向document。
					});
				};
				return this;
			};
			var onDOMReady = function() {
				for ( var i = 0x0; i < readyList.length; i++) {
					readyList[i].apply(document);
				};
				readyList = null;
			};
			var bindReady = function(evt) {
				if (isReady) {//因为IE6,IE7用到了setInterval,所以这里需要判断isReady的状态。
					return;
				}
				isReady = true;
				onDOMReady.call(window);//直接调用onDOMReady()效果一样。
				if (document.removeEventListener) {
					document.removeEventListener(_$[0], bindReady, false);//'DOMContentLoaded'
				} else if (document.attachEvent) {
					document.detachEvent(_$[1], bindReady);//'onreadystatechange'
					if (window == window.top) {
						clearInterval(timer);
						timer = null;
					}
				}
			};
			/**
			 * 监听document是否completely loaded and parsed,yes就call绑定函数bindReady。
			 * stylesheets loading会block绑定函数的执行,但图片不会。
			 * 这里用了三种方法hack不同的浏览器:
			 * 	1、IE9和Chrome,Firefox等主流浏览器:直接绑定DOMContentLoaded时间到document。
			 * 	2、IE8:监听onreadystatechange事件并测试状态。
			 * 	3、IE6,IE7:document.documentElement.doScroll('left')在ready之前会一直抛错。
			 */
			if (document.addEventListener) {//IE9支持document.addEventListener方法
				document.addEventListener(_$[2], bindReady, false);//'DOMContentLoaded'
			} else if (document.attachEvent) {//IE8
				//https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded
				document.attachEvent(_$[3], function() {//'onreadystatechange'
					if ((/loaded|complete/).test(document.readyState))
						bindReady();
				});
				if (window == window.top) {//window == window.top是用来做什么的?
					timer = setInterval(function() {//IE6,IE7
						try {
							isReady || document.documentElement.doScroll(_$[4]);//'left'
						} catch (e) {
							return
						}
						bindReady();
					}, 0x5);
				}
			}
		},
		$ : function() {
			return typeof arguments[0x0] === _$[5] ? document//'string'
					.getElementById(arguments[0x0]) : arguments[0x0];
		},
		extend : function(target, options) {//没用到
			for (name in options) {
				target[name] = options[name];
			}
			return target;
		},
		cookie : function(key, value, options) {
			/**
			 * 下面这段代码负责cookie的添加和删除, 在jquery.cookie.js中删除cookie有专门的方法removeCookie,
			 * 小米在这里把添加和删除合并是为了简便起见。
			 * 不过话说String(value) !== _$[6]有什么用?
			 */
			if (arguments.length > 0x1 && String(value) !== _$[6]) {//6: '[object Object]'
				if (value === null || value === undefined) {
					options.expires = -0x1;
				};
				if (typeof options.expires === _$[7]) {//'number'
					var days = options.expires, t = options.expires = new Date();
					t.setDate(t.getDate() + days);
				};
				value = String(value);
				return (document.cookie = [
						encodeURIComponent(key),
						_$[8],//'='
						options.raw ? value : encodeURIComponent(value),
						options.expires ? _$[9] + options.expires.toUTCString() : _$[10],//'; expires=',用的方法是UTC不是GMT。
						options.path ? _$[11] + options.path : _$[12],//11: '; path='
						options.domain ? _$[13] + options.domain : _$[14],//13: '; domain='
						options.secure ? _$[15] : _$[16] ].join(_$[17]));//15: '; secure'
			};
			/**
			 * 这个判断同样没有意义,代码走到这里说明调用参数只有一个m.cookie(key)或者没有m.cookie(),
			 * 所以value一定是undefined,直接写成options = {}就好了。
			 */
			options = value || {};
			//唉,options.raw!
			var result, decode = options.raw ? function(s) {
				return s;
			} : decodeURIComponent;
			return (result = new RegExp(_$[18] + encodeURIComponent(key)//'(?:^|; )' + key + '=([^;]*)'
					+ _$[19]).exec(document.cookie)) ? decode(result[0x1])
					: null;
		},
		addEvent : (function() {//没用到
			if (document.addEventListener) {
				return function(el, type, fn) {
					el.addEventListener(type, fn, false);
				};
			} else {
				return function(el, type, fn) {
					el.attachEvent(_$[20] + type, function() {//'on'
						return fn.call(el, window.event);//window.event
					});
				};
			}
		})(),
		randomDiff : function(option) {//没用到
			var paras = {
				randomS : 0x1,
				randomE : 0x5
			}, options = m.extend(paras, option || {}), randomNum = Math
					.random()
					* (options.randomE - options.randomS + 0x1)
					+ options.randomS;
			return parseInt(randomNum);
		},
		getQueryString : function(name) {//没用到
			var reg = new RegExp(_$[21] + name + _$[22], _$[23]);//'(^|&)', '=([^&]*)(&|$)', 'i'
			var r = window.location.search.substr(0x1).match(reg);
			if (r != null)
				return unescape(r[0x2]);
			return null;
		},
		creatJs : function(src, elemid) {
			var Scrip = document.createElement(_$[24]);//'script'
			Scrip.src = src;
			if (!!elemid) {
				Scrip.id = elemid;
				if (m.$(elemid)) {
					document.body.removeChild(m.$(elemid));
				}
			}
			document.body.appendChild(Scrip);
		},
		/**
		 * 如果有name='orgin'且value='mapp'的cookie就认为是用户从PC机登录,且删除该cookie并返回,否则就认为是Mobile登录,
		 * 确认后跳转至Mobile登录页面。由此可猜测该cookie在用PC机登录小米首页的时候被创建了,但是Mobile登录时就没有创建或者值不同。
		 * @param url
		 */
		phone : function(url) {
			url = url || _$[25];//25: 'http://m.xiaomi.com'
			if (m.cookie(_$[26]) === _$[27]) {//26: 'orgin', 27: 'mapp'
				m.cookie(_$[28], null, {//'orgin'
					path : _$[29],//'/'
					domain : _$[30]//'.xiaomi.com'
				});
				return
			};
			var sUserAgent = navigator.userAgent;
			if (sUserAgent.indexOf(_$[31]) > -0x1//'Android'
					|| sUserAgent.indexOf(_$[32]) > -0x1//'iPhone'
					|| sUserAgent.indexOf(_$[33]) > -0x1//'iPod'
					|| sUserAgent.indexOf(_$[34]) > -0x1) {//'Symbian'
				location.href = url;
			}
		},
		init : function() {
			var _this = this;
			_this.doms();
		}
	};
	m.init();
})();

var json_1022 = {//这个数据是10月22号抢购的时候截取下来的,传递给hdcontrol的参数。
		"stime": 1382414432,//server端的时间
		"status": {
			"allow": false,
		    "miphone": {
		    	"hdstart": true,
		    	"hdstop": false,
		    	"hdurl": "?_a=20131022_phone_df56ab516d&_op=choose",
		    	"duration": null,
		    	"pmstart": false
		    },
		    "mibox": {
		    	"hdstart": true,
		    	"hdstop": false,
		    	"hdurl": "?_a=20131022_box_f9348273e1&_op=choose",
		    	"duration": null,
		    	"pmstart": false
		    },
		    "mitv": {
		    	"hdstart": true,
		    	"hdstop": false,
		    	"hdurl": "?_a=20131022_mi_tv_ae3cc600f&_op=choose",
		    	"duration": null,
		    	"pmstart": false
		    }
		}
	};
function hdcontrol(json) {//更新client和server的时间差;根据server给的状态位,显示当前手机和电视的购买情况(在售或已售完)。
	var phonestart = json.status.miphone.hdstart, phonestop = json.status.miphone.hdstop, boxstart = json.status.mibox.hdstart, boxstop = json.status.mibox.hdstop;
	servertime = downServertime = json.stime;
	var diffTime = parseInt(servertime - miphoneBuy.localTime());
	m.cookie(_$[35], diffTime, {//'xm_difft_hd'
		path : _$[36],//'/'
		domain : _$[37],//'.xiaomi.com'
		expires : 0x1//一天有效期
	});
	if (isRollStatus) {//点击购买窗口的购买按钮才会将isRollStatus置为true
		if (json.status.allow) {//购买成功?
			if (isPhone === true) {//你买的是手机吗?
				isPhone === false;//===应该是=
				if (json.status.miphone.hdurl == null || json.status.miphone.hdurl == _$[38]) {//''
					window.location.reload();
				} else {
					location.href = _$[39] + json.status.miphone.hdurl;//'http://t.hd.xiaomi.com/s/' + '?_a=20131022_phone_df56ab516d&_op=choose'
				}
			} else if (isBox === true) {//还是买的电视?
				isBox === false;//===应该是=
				if (json.status.mibox.hdurl == _$[40] || json.status.mibox.hdurl == null) {//''
					window.location.reload();
				} else {
					location.href = _$[41] + json.status.mibox.hdurl;//'http://t.hd.xiaomi.com/s/' + '?_a=20131022_box_f9348273e1&_op=choose'
				}
			}
		}
		isRollStatus = false;
	}
	if (phonestart === true && phonestop === false && boxstart === false
			&& boxstop === true) {
		m.cookie(_$[42], 0x1, {//'xm_xt_obox'
			path : _$[43],//'/'
			domain : _$[44],//'.xiaomi.com'
			expires : 0x1
		});
		m.cookie(_$[45], null, {//'xm_xt_ophone'
			path : _$[46],//'/'
			domain : _$[47]//'.xiaomi.com'
		});
		miphoneBuy.box(false);
		stepHtml.five();
	}
	if (phonestart === false && phonestop === true && boxstart === true
			&& boxstop === false) {
		m.cookie(_$[48], 0x1, {//'xm_xt_ophone'
			path : _$[49],
			domain : _$[50],
			expires : 0x1
		});
		m.cookie(_$[51], null, {//'xm_xt_obox'
			path : _$[52],
			domain : _$[53]
		});
		miphoneBuy.box(false);
		stepHtml.six();
	}
	if (phonestart === false && phonestop === true && boxstart === false
			&& boxstop === true) {
		m.cookie(_$[54], 0x1, {//'xm_xt_pre'
			path : _$[55],
			domain : _$[56],
			expires : 0x1
		});
		m.cookie(_$[57], null, {//'xm_xt_obox'
			path : _$[58],
			domain : _$[59]
		});
		m.cookie(_$[60], null, {//'xm_xt_ophone'
			path : _$[61],
			domain : _$[62]
		});
		miphoneBuy.saleOut();
	}
};
var miphoneBuy = {
	localTime : function() {//取client端时间,单位是秒
		return parseInt(new Date().getTime() / 0x3e8);
	},
	jsonInter : function() {//从server取数据并回调hdcontrol函数
		var timestamp = new Date().getTime();//这里的时间取的是本地时间戳
		m.creatJs(_$[63] + timestamp, _$[64]);//63: 'http://tc.hd.xiaomi.com/hdget?callback=hdcontrol&_=', 64: 'jsonp'
	},
	checkCookie : function() {
		var _this = this;
		if (m.cookie(_$[65])) {//'xm_xt_pre'
			_this.saleOut();//对哟,你来的太晚,已全部售完,我的心你不明白--《你把我灌醉》
		} else {
			if (!m.cookie(_$[66])) {//'xm_difft_hd'
				_this.jsonInter();//这里主要用来取client和server的时间差
			}
			setTimeout(function() {
				servertime = downServertime = miphoneBuy.localTime() + parseInt(m.cookie(_$[67]));//'xm_difft_hd',重算一下servertime和downServertime
				_this.jugeStatus();
			}, 0x64);//留一点时间给jsonInter加载js文件和执行
		}
	},
	saleOut : function() {//全部已售完
		if (window.timeInter) {//全没了,通知广大用户这一噩耗,定时器?也不用了!
			clearInterval(timeInter);
		}
		stepHtml.four();
		miphoneBuy.box(false);
	},
	jugeStatus : function() {//更新时间节点和页面状态
		var _this = this;
		_this.timeNode();
		timeInter = window.setInterval(function() {
			_this.timeNode();
			servertime++;
		}, 0x3e8);//1000ms
	},
	configs : {
		startDate : new Date(_$[68]).getTime(),//'10/15/2013  12:00:00'
		preLogMin : 0x1e//30 mins
	},
	timeNode : function() {
		var _this = this;
		var nowTime = servertime * 0x3e8, startTime = _this.configs.startDate, preLogTime = startTime - _this.configs.preLogMin * 0xea60;
		if (m.cookie(_$[69])) {//'xm_xt_pre'
			_this.saleOut();
			return
		}
		if (m.cookie(_$[70])) {//'xm_difft_hd'
			downServertime = miphoneBuy.localTime() + parseInt(m.cookie(_$[71]));//'xm_difft_hd'
		}
		//更新页面信息用的是servertime,而且是以ms为单位;更新倒计时窗口用的是downServertime;
		if (nowTime < preLogTime) {//未进入30分钟倒计时
			stepHtml.one();
			_this.timeOut();
		} else if (nowTime >= preLogTime && nowTime < startTime) {//进入倒计时但尚未开始,提醒用户先登录
			stepHtml.two();
			_this.timeOut();
		} else if (nowTime >= startTime) {//已经开售,正式拉开抢购大幕
			if (m.cookie(_$[72])) {//'xm_xt_obox'
				stepHtml.five();
			} else if (m.cookie(_$[73])) {//'xm_xt_ophone'
				stepHtml.six();
			} else {
				stepHtml.three();
			}
		}
	},
	timeOut : function() {
		var _this = this;
		_this.SetRemainTime();
		if (window.InterValObj) {
			clearInterval(InterValObj);
		}
		/**
		 * 这一个InterValObj定时器用的多余,因为在抢购开始之前timeNode方法本身就会被每秒执行一次,
		 * 于是timeOut也会被每秒执行一次,这里InterValObj相关的代码可以全部去掉,效果一样!
		 */
		InterValObj = window.setInterval(function() {
			_this.SetRemainTime();
		}, 0x3e8);
	},
	SetRemainTime : function() {//更新页面倒计时按钮的时间信息,提醒用户抢购什么时候开始。
		var _this = this, endtime = _this.configs.startDate, setEndtime = endtime / 0x3e8;
		surplusTime = setEndtime - downServertime;
		if (surplusTime >= 0x0) {
			var second = Math.floor(surplusTime % 0x3c), minite = Math
					.floor((surplusTime / 0x3c) % 0x3c), hour = Math
					.floor((surplusTime / 0xe10) % 0x18), day = Math
					.floor((surplusTime / 0x15180) % 0x1e);
			downServertime++;
			var timeArray = [ second.toString(), minite.toString(),
					hour.toString(), day.toString() ];
			var timeText = _$[74] + timeArray[0x2] + _$[75] + timeArray[0x1]//几小时几分几秒后开始
					+ _$[76] + timeArray[0x0] + _$[77];
			if (hour === 0x0) {
				timeText = _$[78] + timeArray[0x1] + _$[79] + timeArray[0x0]//几分几秒后开始
						+ _$[80];
				if (minite === 0x0) {
					timeText = _$[81] + timeArray[0x0] + _$[82];//几秒后开始
				}
			}
			
			if (!!m.$(_$[83])) {//'surTime',倒计时窗口ID
				m.$(_$[84]).innerHTML = timeText;//'surTime'
			}
		} else {
			if (window.InterValObj) {
				clearInterval(InterValObj);
			}
		}
	},
	box : function(bool) {//true: 打开购买窗口,false:关闭购买窗口
		if (bool) {
			var mboxbg = m.$(_$[85]);//'boxbg'
			var mbox = m.$(_$[86]);//'box'
			mboxbg.style.height = Math.max(
					document.documentElement.clientHeight,
					document.documentElement.scrollHeight)
					+ _$[87];//'px'
			mboxbg.style.display = _$[88];//'block'
			mbox.style.display = _$[89];//'block'
		} else {//关闭购买窗口;disable购买按钮并update显示文本为倒计时状态;重置倒计时的读秒
			var mboxbg = m.$(_$[90]);//'boxbg',遮罩层
			var mbox = m.$(_$[91]);//'box',弹出的购买窗口
			mboxbg.style.display = _$[92];//'none'
			mbox.style.display = _$[93];//'none'
			if (window.rollInter) {
				clearInterval(rollInter);
			}
			Util.retime();//下面的count变量已经被重置
			m.$(_$[94]).innerHTML = _$[95] + count + _$[96];//94: 'reback', 95: '重新进入(<span id=\'initCount\'>', 96: '</span>)'
		}
	},
	init : function(option) {
		var _this = this;
		_this.checkCookie();
	}
};
var stepHtml = {//,
	/**
	 * 购买手机:showBox('phone');购买电视:showBox('box')
	 * 凡是带有"购买"字样的都是调用showBox,其他的"查询"和"支付"都是超链接
	 */
	one : function() {//即将开始
		var mhtml = stepHtml.htmlString();
		m.$(_$[97]).innerHTML = mhtml.btn[0x0];//_$[141]: '<span class="untime"><label id="surTime" class="unbtn"></label></span>'
		m.$(_$[98]).innerHTML = mhtml.subTitle[0x0];//_$[147]: ''
		m.$(_$[99]).innerHTML = mhtml.lnks[0x0];//_$[156]: '手机预约查询&电视预约查询'
		m.$(_$[100]).innerHTML = mhtml.phonebtn[0x0];//_$[161]: '<span>1999元(16GB)</span>即将开始'
		m.$(_$[101]).innerHTML = mhtml.tvbtn[0x0];//_$[164]: '<span>2999元</span>即将开始'
		m.$(_$[102]).innerHTML = mhtml.msg[0x0];//_$[151]: ''
		m.$(_$[103]).innerHTML = mhtml.bottombtn[0x0];//_$[167]: '<label class="btn unbtn">即将开始</label>'
	},
	two : function() {//即将开始,提醒用户先登录
		var mhtml = stepHtml.htmlString();
		var miID = (m.cookie(_$[104]));//'userId'
		if (miID) {
			m.$(_$[105]).innerHTML = mhtml.btn[0x0];//_$[141]: '<span class="untime"><label id="surTime" class="unbtn"></label></span>'
		} else {
			m.$(_$[106]).innerHTML = mhtml.btn[0x1];//_$[141]: '<a>提前登录</a>'
		}
		m.$(_$[107]).innerHTML = mhtml.lnks[0x0];//_$[156]: '手机预约查询&电视预约查询'
		m.$(_$[108]).innerHTML = mhtml.subTitle[0x0];//_$[147]: ''
		m.$(_$[109]).innerHTML = mhtml.phonebtn[0x0];//_$[161]: '<span>1999元(16GB)</span>即将开始'
		m.$(_$[110]).innerHTML = mhtml.tvbtn[0x0];//_$[164]: '<span>2999元</span>即将开始'
		m.$(_$[111]).innerHTML = mhtml.msg[0x0];//_$[151]: ''
		m.$(_$[112]).innerHTML = mhtml.bottombtn[0x0];//_$[167]: '<label class="btn unbtn">即将开始</label>'
	},
	three : function() {//小米手机3和小米电视均可购买
		var mhtml = stepHtml.htmlString();
		m.$(_$[113]).innerHTML = mhtml.btn[0x2];//_$[143]: '购买手机&购买电视'
		m.$(_$[114]).innerHTML = mhtml.subTitle[0x0];//_$[147]: ''
		m.$(_$[115]).innerHTML = mhtml.phonebtn[0x1];//_$[162]: '<span>1999元(16GB)</span>立即购买'
		m.$(_$[116]).innerHTML = mhtml.tvbtn[0x1];//_$[165]: '<span>2999元</span>立即购买'
		m.$(_$[117]).innerHTML = mhtml.msg[0x4];//_$[155]: '购机成功用户请在3小时内下单,3小时内支付。支付手机&支付电视'
		m.$(_$[118]).innerHTML = mhtml.lnks[0x0];//_$[156]: '手机预约查询&电视预约查询'
		m.$(_$[119]).innerHTML = mhtml.bottombtn[0x1];//_$[168]: '购买手机'
	},
	four : function() {//全部小米手机3及小米电视已售罄
		var mhtml = stepHtml.htmlString();
		m.$(_$[120]).innerHTML = mhtml.btn[0x3];//_$[144]: '支付手机&支付电视'
		m.$(_$[121]).innerHTML = mhtml.phonebtn[0x2];//_$[163]: '<span>1999元(16GB)</span>立即支付'
		m.$(_$[122]).innerHTML = mhtml.tvbtn[0x2];//_$[166]: '<span>2999元</span>立即支付'
		m.$(_$[123]).innerHTML = mhtml.subTitle[0x3];//_$[150]: '全部小米手机3及小米电视已售罄'
		m.$(_$[124]).innerHTML = mhtml.msg[0x3];//_$[154]: '购机成功用户请在3小时内下单,3小时内支付。'
		m.$(_$[125]).innerHTML = mhtml.lnks[0x3];//_$[159]: '手机购买查询&电视购买查询'
		m.$(_$[126]).innerHTML = mhtml.bottombtn[0x2];//_$[169]: '支付手机'
	},
	five : function() {//小米电视已售罄,您可继续购买小米手机3
		var mhtml = stepHtml.htmlString();
		m.$(_$[127]).innerHTML = mhtml.btn[0x4];//_$[145]: '购买手机&支付电视'
		m.$(_$[128]).innerHTML = mhtml.phonebtn[0x1];//_$[162]: '<span>1999元(16GB)</span>立即购买'
		m.$(_$[129]).innerHTML = mhtml.subTitle[0x2];//_$[149]: '小米电视已售罄,您可继续购买小米手机3'
		m.$(_$[130]).innerHTML = mhtml.tvbtn[0x2];//_$[166]: '<span>2999元</span>立即支付'
		m.$(_$[131]).innerHTML = mhtml.msg[0x1];//_$[152]: '购机成功用户请在3小时内下单,3小时内支付。<a>支付手机</a>'
		m.$(_$[132]).innerHTML = mhtml.lnks[0x1];//_$[157]: '手机预约查询&电视购买查询'
		m.$(_$[133]).innerHTML = mhtml.bottombtn[0x1];//_$[168]: '购买手机'
	},
	six : function() {//小米手机3已售罄,您可继续购买小米电视
		var mhtml = stepHtml.htmlString();
		m.$(_$[134]).innerHTML = mhtml.btn[0x5];//_$[146]: '购买电视&购买电视'
		m.$(_$[135]).innerHTML = mhtml.phonebtn[0x2];//_$[163]: '<span>1999元(16GB)</span>立即支付'
		m.$(_$[136]).innerHTML = mhtml.subTitle[0x1];//_$[148]: '小米手机3已售罄,您可继续购买小米电视'
		m.$(_$[137]).innerHTML = mhtml.tvbtn[0x1];//_$[165]: '<span>2999元</span>立即购买'
		m.$(_$[138]).innerHTML = mhtml.msg[0x2];//_$[153]: '购机成功用户请在3小时内下单,3小时内支付。<a>支付电视</a>'
		m.$(_$[139]).innerHTML = mhtml.lnks[0x2];//_$[158]: '手机购买查询&电视预约查询'
		m.$(_$[140]).innerHTML = mhtml.bottombtn[0x2];//_$[168]: '支付手机'
	},
	htmlString : function() {
		var htmlSum = {
			btn : [ _$[141], _$[142], _$[143], _$[144], _$[145], _$[146] ],//hdBtns
			subTitle : [ _$[147], _$[148], _$[149], _$[150], ],//hdSubTitle
			msg : [ _$[151], _$[152], _$[153], _$[154], _$[155] ],//hdMsg
			lnks : [ _$[156], _$[157], _$[158], _$[159], _$[160], ],//hdLnks
			phonebtn : [ _$[161], _$[162], _$[163] ],//miphone
			tvbtn : [ _$[164], _$[165], _$[166] ],//mitv
			bottombtn : [ _$[167], _$[168], _$[169] ]//bottombtn
		};
		return htmlSum;
	}
};
var randomCount = parseInt(Math.random() * (0xa - 0x5 + 0x1) + 0x5), count = randomCount, CONFIG = {
	count : randomCount
}, Util = {
	time : function() {
		var b = m.$(_$[170]);//'reback',<a id="reback" class="reback_btn_next">进入活动</a>
		if (count === 0x0) {
			b.innerHTML = _$[171];//'进入活动'
			b.className = _$[172];//'reback_btn_next'
			this.start();
			return false;
		}
		count = count - 0x1;
		//只需要更新initCount元素的文本就好了,没必要更新reback的html
		b.innerHTML = _$[173] + count + _$[174];//173: '重新进入(<span id=\'initCount\'>', 174: '</span>)'
	},
	start : function() {
		var me = this, reback = m.$(_$[175]);//'reback'
		reback.onclick = function() {
			/**
			 * 向server发送请求,根据返回状态判断是否抢购成功;
			 * Disable购买按钮;
			 * 注意此时rollInter并没有被清除,也就是说从购买按钮已经可以点击到你真正点击的这段时间内Util.time一直
			 * 在执行,这里最好把rollInter清除掉。
			 */
			isRollStatus = true;//开始尝试购买,抢购进入高潮!
			miphoneBuy.jsonInter();
			me.retime();
			reback.onclick = null;
			return false;
		};
	},
	retime : function() {//重置购买按钮为disable状态;重置倒计时读秒。
		m.$(_$[176]).className = _$[177];//176: 'reback', 177: 'reback_btn'
		count = CONFIG.count;
	}
};
var loginInfo = {
	data : {
		userId : 0x0,
		userName : _$[178]//''
	},
	init : function() {
		this.data.userId = m.cookie(_$[179]);//'userId'
		if (!this.data.userId)
			return false;
		//这里this.data.userId已经是true了,所以this.data.userName一定被赋值为m.cookie('XM_' + this.data.userId + '_UN')
		this.data.userName = (this.data.userId) ? m.cookie(_$[180]//'XM_'
				+ this.data.userId + _$[181]) : _$[182];//181: '_UN', 182: ''
		if (this.data.userName == null || this.data.userName == _$[183]) {//''
			var script = document.createElement(_$[184]);//'script'
			//185: 'https://account.xiaomi.com/pass/userInfoJsonP?userId=', 186: '&callback=loginInfo.getAccountInfo'
			script.src = _$[185] + this.data.userId + _$[186];
			script.type = _$[187];//'text/javascript'
			script.async = true;//http://www.w3schools.com/tags/att_script_async.asp
			document.getElementsByTagName(_$[188])[0x0].appendChild(script);//'head'
		} else {
			this.upUserInfo();
		}
	},
	upUserInfo : function() {
		var nickName = this.data.userName;
		if (!!m.$(_$[189])) {//'LoginArea'
			//'LoginArea', '欢迎您 ', '!<a href=\'http://order.xiaomi.com/site/logout\'>退出</a>'
			m.$(_$[190]).innerHTML = _$[191] + nickName + _$[192];
			m.$(_$[193]).style.paddingLeft = _$[194];//'LoginArea', '12px'
		}
	},
//	{
//		"uniqName": "暗影萨满",
//		"miliaoInfo": {
//			"icon": "",
//			"nickName": "暗影萨满"
//		},
//		"EM": {
//			"binded": true,
//			"address": "暗影萨满@dota.com"
//		},
//		"PH": {
//			"binded": true,
//			"address": "186********"
//		},
//		"userId": 28******
//	}
	getAccountInfo : function(data) {
		if (data.userId) {
			this.data.userName = (data.uniqName) ? data.uniqName : data.userId;
			var option = {
				path : _$[195],//'/'
				domain : _$[196]//'.xiaomi.com'
			};
			m.cookie(_$[197] + this.data.userId + _$[198], this.data.userName, option);//'XM_', '_UN'
			this.upUserInfo();
		}
	}
};
function showBox(gtype) {
	if (m.cookie(_$[199])) {//'userId'
		if (gtype === _$[200]) {//'phone'
			isPhone = true;
		} else if (gtype === _$[201]) {//'box'
			isBox = true;
		}
		miphoneBuy.box(true);
		m.$(_$[202]).innerHTML = CONFIG.count;//'initCount',重置购买窗口的购买按钮的倒计时读秒
		rollInter = window.setInterval(_$[203], 0x3e8);//'Util.time()',每秒执行一次
	} else {
		location.href = _$[204];
	}
};
m.ready(function() {
	m.phone(_$[205]);//'http://p.www.xiaomi.com/m/zt/open/index.html'
	miphoneBuy.init();
	loginInfo.init();
});

 

第一步: 把超长的数组_$解码出来

我的办法是把它遍历出来之后放到textarea中,之后复制出来就好了,下面的sce.js只包含_$数组:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="sce.js"></script>
</head>
	<textarea id="pp" cols="150" rows="30"></textarea>
	<script type="text/javascript">
	for (var o in _$) {
		document.getElementById("pp").innerHTML += "'" +  _$[o].replace(/'/g, "\\'") + "\',//" + o + "\n";
	}
	</script>
</html>

 

第二步:分析代码的执行顺序和功能

执行顺序如下,功能细节见代码:

  1. m.init() >> m.doms()
  2. bindReady() >> onDOMReady()
  3. m.phone()
  4. miphoneBuy.init() >> miphoneBuy.checkCookie() >> miphoneBuy.jugeStatus(),此时开始启动定时器timeInter,每秒调用一次timeNode,直至全部售完,抢购结束!
  5. loginInfo.init()

cookie的作用如下:

  • 'xm_xt_obox' ,电视已售完
  • 'xm_xt_obox' ,电视已售完
  • 'xm_xt_pre' ,全部售完
  • 'xm_difft_hd',client和server时间差
  • 'orgin' == 'mapp',PC机登陆,否则认为是Mobile登陆

That‘s it.

分享到:
评论
3 楼 Mossad 2013-11-20  
duducs 写道
第二步是 像huangzhir以前 跳过页面等待,直接提交服务端排队 吗 

不是,我只是单纯的分析代码的执行顺序而已。
2 楼 duducs 2013-11-18  
第二步是 像huangzhir以前 跳过页面等待,直接提交服务端排队 吗 
1 楼 zrmpop 2013-11-13  
  thanks

相关推荐

    享受代码的快乐--小米抢购前端代码分析

    在本文中,我们将深入探讨“享受代码的快乐--小米抢购前端代码分析”这一主题,主要涉及源码解析和工具应用。通过分析博主黄之锐在iteye博客上分享的文章,我们可以了解到小米抢购页面的前端实现细节以及相关技术的...

    仿小米官网首页2021最新版本前端代码【只有前端代码】

    在本项目中,我们主要关注的是“仿小米官网首页2021最新版本前端代码”。这个项目提供了构建一个与小米官网2021年最新设计风格相似的前端页面所需的所有资源,包括HTML、CSS和JavaScript文件。让我们逐一深入探讨...

    小米官网前端页面代码

    除此之外,小米官网的前端代码可能还涉及到其他技术,如: - SEO优化:通过元标签(meta tags)和语义化HTML提高搜索引擎可见性。 - AJAX调用API:与后端服务器通信,获取产品信息、评论等实时数据。 - Web字体:...

    小米抢购源代码

    小米抢购源代码, using System; using System.Threading.Tasks; using System.Windows.Forms; using System.Timers; using Newtonsoft.Json; using System.Text.RegularExpressions; using System.Configuration; ...

    小米官网源代码

    总之,通过分析小米官网的源代码,我们可以学习到前端开发的最新趋势和技术实践,包括但不限于前端框架的应用、响应式设计、性能优化、安全防护和SEO策略等。这对于提升自己的前端技能、了解行业标准以及解决实际...

    小米抢购js代码反混淆(java+js实现)

    对于小米抢购页面的JS代码,混淆可能是为了防止恶意用户分析和利用抢购逻辑。 要对混淆的JS代码进行反混淆,我们需要遵循以下步骤: 1. **代码解析**:使用JavaScript解析库,如Esprima,将混淆的JS代码转化为抽象...

    仿小米商城前端模板源码下载

    本文将详细解析“仿小米商城前端模板源码”的相关知识点,该源码是一个适用于手机分类商城的小程序前端项目,包含了9个主要页面,涵盖了用户在购物过程中可能涉及到的各种功能。 首先,我们要理解“前端”这一概念...

    小米官网前端代码.rar

    本资源完整还原小米官网静态页面,包含html,css以及页面包含的所有图片及字体,字体符号使用方法,请参考阿里巴巴矢量图库官网:https://www.iconfont.cn/。效果预览链接:...

    用HTML写一个小米商城

    还可以使用JavaScript库和框架,如jQuery简化DOM操作,React或Vue.js构建组件化、状态管理更高效的前端应用。 在实际开发过程中,我们还需要考虑到SEO(搜索引擎优化),确保HTML标签的合理使用以便搜索引擎理解...

    小米产品抢购软件

    【小米产品抢购软件】是一种专门针对小米公司热门产品的在线抢购辅助工具,它旨在帮助用户提高购买小米手机、智能设备等热门商品的成功率。在众多消费者对小米新品的追捧中,由于库存有限,抢购变得极具竞争性,而这...

    小米抢购页面脚本研究

    压缩包内的文件名“极致-10月22日,小米手机3、小米电视、小米手机2S、小米盒子、红米手机发售.htm”可能是抢购活动的页面存档,可能包含了页面结构、脚本以及抢购时的具体交互逻辑。研究者可能通过分析这个页面的...

    前端项目——小米官网首页

    在本项目中,“前端项目——小米官网首页”旨在模拟实现小米官网的主页,采用的是基础的HTML、CSS技术,特别强调了对div和css的运用。这个项目对于初学者来说是一个很好的实践机会,因为它不涉及复杂的JavaScript...

    微信小程序 商城模板 小米商城 (源代码+截图)

    微信小程序 商城模板 小米商城 (源代码+截图)微信小程序 商城模板 小米商城 (源代码+截图)微信小程序 商城模板 小米商城 (源代码+截图)微信小程序 商城模板 小米商城 (源代码+截图)微信小程序 商城模板 小米...

    xiaomi.zip_c# 抢购_小米手机抢购_小米电视_抢购_抢购 c++

    本文将深入探讨标题为"xiaomi.zip_c# 抢购_小米手机抢购_小米电视_抢购_抢购 c++"的项目,它涉及到使用C#语言开发的抢购器,专门针对小米手机和电视等产品。 首先,我们要理解的是C#(读作"C sharp")是一种面向...

    HTML小米商城代码 注册 登入

    10. **XHTML**: XHTML是HTML与XML的结合体,要求语法更加严格,但现代浏览器通常能很好地解析HTML5语法。 以上是构建小米商城注册和登录页面时可能会涉及的一些HTML知识点。实际开发中,可能还需要结合JavaScript...

    前端web结课作业 小米商城 纯HTML+CSS

    【压缩包子文件的文件名称列表】:“小米商城(自行解压)”说明压缩包内包含了整个项目的源代码文件、图片资源和其他可能的素材。解压后,我们可以期待找到以下几类文件: 1. HTML文件:这些文件包含网页的结构,...

    网页前端项目小米商城源码

    【网页前端项目小米商城源码】是一个用于学习和实践网页设计的开源项目,它复现了小米商城的主页面,提供了基础的用户交互和布局展示。这个项目可以帮助开发者理解和掌握前端开发的基本技能,包括HTML、CSS、...

    圣道小米抢购神器5.0中文绿色免费版

    圣道小米抢购软件是一款免费高效的小米抢购秒杀工具。软件采用P2P加速技术,抢购更迅速,更稳定,更高速,更高效。软件绿色便捷,永久免费,是小米抢购神器。 圣道小米抢购软件 功能特点 1.高速抢购 P2P加速技术,...

Global site tag (gtag.js) - Google Analytics