Analysis and Optimization of JavaScript example Code for Running Lantern Lucky Draw (II)

  • 2020-12-21 17:58:25
  • OfStack

In the last article, I introduced JavaScript to realize the example code analysis and optimization of running lantern Lucky draw (1), since it is to write a plug-in. So something called a "plug-in" must have some characteristic that satisfies our development needs or improves our development efficiency. So what are the basic features of something called a plug-in? Let's conclude with the following:

1. Some basic features of JavaScript plug-in 1:

Configuration 1 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;
Have the function of destroying variables and parameters;
If we write plug-ins according to the above characteristics, we can summarize a basic code structure, let's look at each one:

1. Keep the plug-in configuration as simple as possible

The container nodes are configured in html


// Here, node-type="reward-area"  Is the container node that identifies our plug-in 
<div class="re-area" node-type="reward-area" >

Initializes the plug-in after DOM is loaded


$(function() {
// Here,  test  It's the container  class
window.LightRotate.init($('[node-type=reward-area]'));
});

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

JavaScript is the block-scoped identifier for function. So how do we declare our variable so that it doesn't contaminate the global variable?
Here we need to use 1 JavaScript function self-execution knowledge point. The code is as follows:


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

3. Reuse functional code in different places

This involves our object-oriented approach, abstracting our functional code into objects, and instantiating objects when we need to use them. So let's continue with the code in Part 2,


//
(function($){
//  Create function objects 
var LightRotate = function (select) {
// do something
};
LightRotate.init = function (select) {
var _this = this;
// Instantiate different objects according to different containers 
select.each(function () {
new _this($(this));
});
};
window.LightRotate = LightRotate;
})(jQuery);

4. Users can customize functional parameters

First we should have a default parameter setting, such as the following


//
(function($){
//  Create function objects 
var LightRotate = function (select) {
//  Custom parameters 
this.setting = {
liAutoPlay: false, // Whether the surrounding lights rotate automatically 
roLiSpeed: 100, // The speed at which the lamp rotates ms
roPrSpeed: 200, // Prize rotation speed ms
liDirection: true, // Direction of rotation  true  Positive direction  false  In the opposite direction 
randomPrize: false // Whether the Spaces are randomly selected 
};
};
LightRotate.init = function (select) {
var _this = this;
// Instantiate different objects according to different containers 
select.each(function () {
new _this($(this));
});
};
window.LightRotate = LightRotate;
})(jQuery);

In fact, the user can modify our JavaScript file to complete the customization. But in order to make our price difference useful enough, for example, our users don't understand js at all? What to do?
This allows us to configure these parameters in html with custom properties, as follows:


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

This allows the user to configure the parameters of the current container run only within the node of html. This benefit also enables separate configuration parameters for different containers on the 1 page, reducing coupling.

So how do we get these parameters in js? In the code above, you already have the function object function. So what if we want to extend the object method to get the user's custom parameters? We generally use prototype stuff to extend the methods of our existing objects, as follows:


//
(function($){
//  Create function objects 
var LightRotate = function (select) {
//  Custom parameters 
this.setting = {
liAutoPlay: false, // Whether the surrounding lights rotate automatically 
roLiSpeed: 100, // The speed at which the lamp rotates ms
roPrSpeed: 200, // Prize rotation speed ms
liDirection: true, // Direction of rotation  true  Positive direction  false  In the opposite direction 
randomPrize: false // Whether the Spaces are randomly selected 
};
// This calls the method of the object that gets the user-defined parameters and merges the default parameters 
$.extend(_this.setting, _this.getSettingUser());
};
LightRotate.prototype = {
// Extends the method for getting user-defined parameters 
getSettingUser: function () {
var userSetting = this.LightArea.attr('data-setting');
if (userSetting && userSetting !== '') {
return $.parseJSON(userSetting);
} else {
return {};
}
}
} ; 
LightRotate.init = function (select) {
var _this = this;
// Instantiate different objects according to different containers 
select.each(function () {
new _this($(this));
});
};
window.LightRotate = LightRotate;
})(jQuery);

5. Function of destroying variables and parameters;

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


LightRotate.prototype = {
// Extends the method for getting user-defined parameters 
getSettingUser: function () {
var userSetting = this.LightArea.attr('data-setting');
if (userSetting && userSetting !== '') {
return $.parseJSON(userSetting);
} else {
return {};
}
},
// Destroy object parameter 
destory: function () {
$(_this.LightArea).off();
this.closeAnimation();
this.rewardTimer = null;
}
} ; 

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

2. Plug-in development and optimization examples

It 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 didn't think about my code structure in detail, so Game provided an opportunity for its subsequent optimization.

You can see from the timer content in the previous section that JavaScript is single-threaded. so

If 1 piece of code runs inefficiently, it will affect subsequent code execution. So for JavaScript, code optimization is a must.
Let's take a look at what our running Lights plugin should do:

Can control whether the light automatically play;
The rotation direction of the lamp can be controlled;
The rotation speed of the lamp can be controlled;
The spinning speed of the prize can be controlled;
The development process of these function points will not be described in detail here, just the optimization process. If you are interested, please refer to the source code address attached at the end of my article for download and reading.

1. "Sequence" to obtain the optimization of the rotation lamp code

Since I use absolute positioning for the lights around me, I need to get their list "sequentially" and then operate.

First get the DOM node.


// Get the peripheral light, and you can see that I'm using more selectors here 1 a  select Is to get some elements under the current container to avoid conflicts when more than one container exists 
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');

The list of DOM elements for the lamp node should then be obtained "sequentially".

Here's what I did for version 1:


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]);
}

Since the "down" and "left" lights need to be in reverse order, I used two inverted for loops, and when the loop occurs, we should all be thinking about whether our code has room for optimization.

The optimized code looks like this, where I've reduced the number of loops by four


$(function() {
// Here,  test  It's the container  class
window.LightRotate.init($('[node-type=reward-area]'));
});
0

In reverse order, I used the reverse method of the native Array object.

2. Use closures to optimize sequential looping

In order to make our "lights" run in sequence, the idea of version 1 is:

Give each of the lights (note, here is each of the lights, sin... Sin...). Define an setTimeout(), the execution time is the number of order to join the js execution queue.
The code looks like this:


$(function() {
// Here,  test  It's the container  class
window.LightRotate.init($('[node-type=reward-area]'));
});
1

The downside of this writing is obvious: if I had 100 "lights" then I would add 100 setTimeout() to the current js execution queue. Again, I'm using an for loop, which adds to the time complexity. The efficiency of code execution has declined again.

After some reflection, the "closure" in JavaScript fits my current usage scenario, so I want to optimize it with closure. The optimized code is as follows:


$(function() {
// Here,  test  It's the container  class
window.LightRotate.init($('[node-type=reward-area]'));
});
2

The above code clearly shows two advantages: first, it reduces the use of for loops and reduces the time complexity of the code, and second, I only create 1 setInterval() in the queue where the current code is executing. Reduces the complexity of the execution queue.

On JavaScript implementation of running lantern lucky draw example code analysis and optimization (2) relevant knowledge to you here, I hope this article will be helpful to you.


Related articles: