Home  >  Article  >  Web Front-end  >  JavaScript implementation of marquee lottery event example code analysis and optimization (2)_javascript skills

JavaScript implementation of marquee lottery event example code analysis and optimization (2)_javascript skills

WBOY
WBOYOriginal
2016-05-16 15:15:291200browse

In the last article, I introduced you to JavaScript implementation of marquee lottery event example code analysis and optimization (1) , since we need to write a plug-in. Then something called a "plug-in" must have certain characteristics that can meet our daily development needs or improve our development efficiency. So what are the basic characteristics that something called a plug-in should have? Let’s sum it up:

1. Some basic features of JavaScript plug-ins:

Configuration must be simple
Variables defined in the plug-in do not pollute global variables;
The same piece of code can be reused in different places;
Users can customize their own function parameters;
Has the function of destroying variables and parameters;
If we write a plug-in according to the above characteristics, we can summarize a basic code structure. Let’s look at it one by one:

1. Plug-in configuration should be as simple as possible

Configuring container nodes in html

//这里的node-type="reward-area" 是标识我们插件的容器节点
<div class="re-area" node-type="reward-area" >

Initialize the plug-in after DOM loading is completed

$(function() {
//这里的 test 是代表容器的 class
window.LightRotate.init($('[node-type=reward-area]'));
});

2. Variables defined in the plug-in do not pollute global variables

JavaScript’s identifier with block-level scope is function. So how do we declare our variables so that they do not pollute global variables?
Here we need to use the knowledge of self-execution of a JavaScript function. The code is as follows:

(function(){
// do something
})();

3. Reuse function code in different places

This requires us to use our object-oriented knowledge points to abstract our functional code into objects. When we need to use it, we can instantiate the object. Then let’s continue writing the code in the second part,

//
(function($){
// 创建功能对象
var LightRotate = function (select) {
// do something
};
LightRotate.init = function (select) {
var _this = this;
//根据不同的容器实例化不同的对象
select.each(function () {
new _this($(this));
});
};
window.LightRotate = LightRotate;
})(jQuery);

4. Users can customize function parameters

First we should have default parameter settings, such as the following

//
(function($){
// 创建功能对象
var LightRotate = function (select) {
// 自定义的参数
this.setting = {
liAutoPlay: false, //周围的灯是否自动旋转
roLiSpeed: 100, //灯旋转的速度ms
roPrSpeed: 200, //奖品旋转速度ms
liDirection: true, //旋转方向 true 正方向 false 反方向
randomPrize: false //空格是否随机选取
};
};
LightRotate.init = function (select) {
var _this = this;
//根据不同的容器实例化不同的对象
select.each(function () {
new _this($(this));
});
};
window.LightRotate = LightRotate;
})(jQuery);

In fact, if written like this, users can already modify our JavaScript files to complete customization. But in order to make our price difference easy to use, for example, what if our users don’t understand js at all? what to do?
In this way, we can configure these parameters in html using custom attributes, as follows:

<div class="re-area" node-type="reward-area" data-setting='{
"liAutoPlay":false,
"roLiSpeed":100,
"roPrSpeed":200,
"liDirection":true,
"randomPrize":false}'>

In this way, users only need to configure the parameters of the current container running in the html node. This benefit also allows different containers on the same page to configure parameters separately, reducing coupling.

So how do we get these parameters in js? In the above code, there are already functional object functions. So we want to extend the object method to obtain the user's custom parameters, what should we do? We generally use prototype things to extend the methods of our existing objects. The code is as follows:

//
(function($){
// 创建功能对象
var LightRotate = function (select) {
// 自定义的参数
this.setting = {
liAutoPlay: false, //周围的灯是否自动旋转
roLiSpeed: 100, //灯旋转的速度ms
roPrSpeed: 200, //奖品旋转速度ms
liDirection: true, //旋转方向 true 正方向 false 反方向
randomPrize: false //空格是否随机选取
};
//这里调用对象的获取用户自定义参数的方法,并且将默认参数合并
$.extend(_this.setting, _this.getSettingUser());
};
LightRotate.prototype = {
//扩展获取用户自定义参数的方法
getSettingUser: function () {
var userSetting = this.LightArea.attr('data-setting');
if (userSetting && userSetting !== '') {
return $.parseJSON(userSetting);
} else {
return {};
}
}
};
LightRotate.init = function (select) {
var _this = this;
//根据不同的容器实例化不同的对象
select.each(function () {
new _this($(this));
});
};
window.LightRotate = LightRotate;
})(jQuery);

5. The function of destroying variables and parameters;

The last one is that our plug-in should have the function of destroying its own variables and parameters. How should we write it? Or continue to extend the callable method of the functional object based on the above code. The code is as follows:

LightRotate.prototype = {
//扩展获取用户自定义参数的方法
getSettingUser: function () {
var userSetting = this.LightArea.attr('data-setting');
if (userSetting && userSetting !== '') {
return $.parseJSON(userSetting);
} else {
return {};
}
},
//销毁对象参数
destory: function () {
$(_this.LightArea).off();
this.closeAnimation();
this.rewardTimer = null;
}
};

From the above content, we can roughly understand the basic functions that a mature plug-in should have.

2. Plug-in development and optimization examples

It just so happened that this project was an urgent project before the Spring Festival holiday. At that time, in order to catch up with the schedule, I did not think about my code structure in detail, which provided opportunities for subsequent optimization of myself.

From the content of the timer introduced in the previous section, we can know that JavaScript is single-threaded. So

If a piece of code runs very inefficiently, it will affect the execution of subsequent code. So for JavaScript, code optimization is a must.
Let’s first take a look at what functions our “marquee” plug-in should have:

Be able to control whether the lights play automatically;
The rotation direction of the light can be controlled;
The rotation speed of the light can be controlled;
The rotation speed of the prize can be controlled;
The development process of these function points will not be introduced in detail here, only the optimization process will be introduced. If you are interested, you can see the source code address attached at the end of my article to download and read.

1. Optimization of "sequential" acquisition of rotating light code

Because I use absolute positioning for the surrounding lights, I need to get their list "sequentially" and then operate.

First get the DOM node.

//获取外围的灯,可以看到我这里使用的选择器多了一个 select,是为了获取当前容器下的某些元素,避免有多个容器存在时冲突
this.topLight = $('[node-type=re-top]', select).find('span');
this.rightLight = $('[node-type=re-right]', select).find('span');
this.bottomLight = $('[node-type=re-bottom]', select).find('span');
this.leftLight = $('[node-type=re-left]', select).find('span');

Then the list of DOM elements of the "light" node should be obtained "sequentially".

My first version is like this:

Zepto(topLight).each(function() {
lightList.push(this);
});
Zepto(rightLight).each(function() {
lightList.push(this);
});
for (var j = bottomLight.length - 1; j >= 0; j--) {
lightList.push(bottomLight[j]);
}
for (var m = leftLight.length - 1; m >= 0; m--) {
lightList.push(leftLight[m]);
}

Because the lights in the "down" and "left" directions need to be in reverse order, I used two for loops in reverse order. In fact, when loops appear, we should all think about whether there is room for optimization in our code. .

The optimized code looks like this, here I have reduced the use of 4 loops

function () {
var lightList = [];
var bottomRever;
var leftRever;
bottomRever = Array.from(this.bottomLight).reverse();
leftRever = Array.from(this.leftLight).reverse();
lightList = Array.from(this.topLight).concat(Array.from(this.rightLight));
lightList = lightList.concat(bottomRever);
lightList = lightList.concat(leftRever);
}

列表倒序我使用了原生 Array对象的reverse方法。

2.使用“闭包”优化顺序循环播

为了能够使我们的“灯”顺序的跑起来,第一版的思路是:

给每一个“灯”(注意,这里是每一个,罪过…罪过…)定义一个setTimeout(),执行时间就是数序的加入 js 执行队列中去。
代码是下面这样子的:

var zepto_light = Zepto(lightList);
var changeTime = 100;
var lightLength = zepto_light.length;
var totleTime = changeTime * lightLength;
function lightOpen() {
for (var i = 0; i < lightLength; i++) {
(function temp(i) {
lightTimer = setTimeout(function() {
if (stopAnimation === false) {
Zepto(zepto_light).removeClass('light_open');
Zepto(zepto_light[i]).addClass("light_open");
} else {
return;
}
}, changeTime * i);
})(i);
}
}

这样子写的缺点很明显:如果我有100个“灯”那么就会在当前的 js 执行队列中加入100个setTimeout(),再次强调的是我这里又使用了for循环,在时间复杂度上又增加了。代码的执行效率又下降了。

后来思考了下,JavaScript 中“闭包”符合我当前的使用场景,就想着用闭包优化一下,优化后代码如下:

lightRun: function () {
var _this = this;
function tempFunc() {
var lightList = _this.getLightList();
var lightLength = lightList.length;
var i = 0;
return function () {
$(lightList, _this.LightArea).removeClass('light_open');
$(lightList[i], _this.LightArea).addClass("light_open");
i++;
//使一轮循环结束后能够继续下次循环
if (i === lightLength) {
i = 0;
}
};
}
var lightRunFunc = tempFunc();
lightRunFunc();
_this.lightInterVal = setInterval(lightRunFunc, _this.setting.roLiSpeed);
}

由以上的代码可以很明显的发现两个优点:第一,就是减少了 for循环的使用,降低了代码的时间复杂度,第二就是,每次我仅仅在当前代码执行的队列中创建一个setInterval()。减小了执行队列的复杂度。

关于JavaScript实现跑马灯抽奖活动实例代码解析与优化(二)的相关知识就给大家介绍到这里,希望本文所述对大家有所帮助。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn