JavaScript code parsing and optimization for the example of the lantern draw activity (2 ).
In the previous article, I introduced the code parsing and optimization of the example code for the JavaScript Implementation of the lantern draw activity (I). Since it is necessary to write a plug-in. Plug-ins certainly have some characteristics that can meet our development needs or improve our development efficiency. What are the basic features of plug-ins? Let's summarize:
1. Some basic features of the JavaScript plug-in:
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;
You can customize function parameters;
Destroys variables and parameters;
If you write the plug-in based on the above features, we can summarize a basic code structure, one by one:
1. Plug-in configuration should be as simple as possible
Configure container nodes in html
// Here node-type = "reward-area" is the container node that identifies our plug-in <div class = "re-area" node-type = "reward-area">
Initialize the plug-in after DOM loading.
$ (Function () {// here test represents the classwindow. LightRotate. init of the container ($ ('[node-type = reward-area]');});
2. variables defined in the plug-in do not pollute global variables
The identifier with block-level scope in JavaScript is a function. So how can we declare our variables so that they do not pollute global variables?
Here we need to use a JavaScript function self-execution knowledge point. The Code is as follows:
(function(){// do something})();
3. Reuse functional code in different places
This requires the use of our object-oriented knowledge points to abstract our functional code into an object. When we need to use it, instantiate the object. Then we continue to write the second part of the code,
// (Function ($) {// CREATE function object var LightRotate = function (select) {// do something}; LightRotate. init = function (select) {var _ this = this; // instantiate different select objects based on different containers. each (function () {new _ this ($ (this) ;}) ;}; window. lightRotate = LightRotate;}) (jQuery );
4. You can customize function parameters.
First, we should have default parameter settings, such as the following
// (Function ($) {// create a function object var LightRotate = function (select) {// custom parameter this. setting = {liAutoPlay: false, // whether the surrounding lights are automatically rotated roLiSpeed: 100, // msroPrSpeed: 200, // prize rotation speed msliDirection: true, // orientation: true; positive direction: false; reverse direction: randomPrize: false // random selection of spaces}; LightRotate. init = function (select) {var _ this = this; // instantiate different select objects based on different containers. each (function () {new _ this ($ (this) ;}) ;}; window. lightRotate = LightRotate;}) (jQuery );
In fact, users can modify our JavaScript file to customize it. But in order to make the price difference easy enough, for example, our users do not understand js at all? What should I do?
In this way, we can configure these parameters in html with custom attributes, as shown below:
<div class="re-area" node-type="reward-area" data-setting='{"liAutoPlay":false,"roLiSpeed":100,"roPrSpeed":200,"liDirection":true,"randomPrize":false}'>
In this way, you only need to configure the parameters for running the current container in the html node. This also enables different containers on the same page to configure parameters separately to reduce coupling.
How can we obtain these parameters in js? In the code above, function object functions are available. What should we do if we want to extend the object method to obtain user-defined parameters? We generally use prototype to extend our existing object methods. The Code is as follows:
// (Function ($) {// create a function object var LightRotate = function (select) {// custom parameter this. setting = {liAutoPlay: false, // whether the surrounding lights are automatically rotated roLiSpeed: 100, // msroPrSpeed: 200, // prize rotation speed msliDirection: true, // The rotation direction is true. The positive direction is false. The reverse direction is "randomPrize: false". // determines whether a space is randomly selected. // The method for obtaining User-Defined parameters of an object is called here, and merge the default parameters $. extend (_ this. setting, _ this. getSettingUser () ;}; LightRotate. prototype = {// extended method for getting User-Defined parameters getSettingUser: function () {var us ErSetting = this. LightArea. attr ('data-setting'); if (userSetting & userSetting! = '') {Return $. parseJSON (userSetting);} else {return {};}}; LightRotate. init = function (select) {var _ this = this; // instantiate different select objects based on different containers. each (function () {new _ this ($ (this) ;}) ;}; window. lightRotate = LightRotate;}) (jQuery );
5. Destroy the functions of variables and parameters;
The last one is that our plug-in should have the function of destroying its own variables and parameters. What should we do? You can continue to extend the function object calling method based on the above Code. The Code is as follows:
LightRotate. prototype = {// extended 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 content, we can roughly understand the basic functions that a mature plug-in should have.
2. Example of plug-in development and optimization
This project was an urgent project before the Spring Festival holiday. At that time, I did not think about my code structure in detail to catch up with the progress, which provided an opportunity for me to optimize the program.
The timer content introduced in the previous section shows that JavaScript is single-threaded. So
If the running efficiency of a piece of code is low, subsequent code execution will be affected. Therefore, code optimization is required for JavaScript.
First, let's take a look at the functions of our "marquee" plug-in:
Controls whether the light is automatically played;
The rotation direction of the lamp can be controlled;
The rotation speed of the lamp can be controlled;
The rotation speed of the prize can be controlled;
Here we will not detail the development process of these functional points, but will only introduce the optimization process. If you are interested, you can refer to the Source Code address appended to my article for download and reading.
1. "order" to obtain the optimization of the revolving lamp code
Because I use absolute positioning to locate the lights around, I need to "order" them to get their list and then operate.
First, obtain the DOM node.
// Obtain the peripheral light. We can see that the selector I use here has a select option, which is used to obtain some elements under the current container and avoid conflict when multiple containers exist. 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 we should "sequentially" Get the DOM element list of the "lamp" node.
My first version does 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 lower and left directions need to be in reverse order, I use two reverse for loops. In fact, when a loop appears, we should all think about whether our code has room for optimization.
The optimized code is like this. Here I have reduced the number of cycles.
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);}
In the reverse list, I used the reverse Method of the native Array object.
2. Use closure to optimize sequential loop playbackRelease
In order to make our "Lights" run in sequence, the idea of the first version is:
For every "lamp" (Note: Here is every, sin... Sin ...) Defines a setTimeout (), and the execution time is to add the data in the number order to the js execution queue.
The Code is as follows:
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);}}
The disadvantage of writing in this way is obvious: If I have 100 "Lights", 100 setTimeout () will be added to the current js execution queue (), I once again stressed that I have used the for loop here, increasing the time complexity. The code execution efficiency is reduced.
Later I thought about how to use the closure in JavaScript to optimize it. The code after optimization is as follows:
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 ++; // enables the next loop to continue after the end of a loop if (I = lightLength) {I = 0 ;}};} var lightRunFunc = tempFunc (); lightRunFunc (); _ this. lightInterVal = setInterval (lightRunFunc, _ this. setting. roLiSpeed );}
The above code can clearly discover two advantages: first, reduce the use of the for Loop, reduce the time complexity of the code, and second, each time I create a setInterval () in the queue where the current code is executed (). This reduces the complexity of the execution queue.
This article describes how to parse and optimize the code of the example code for the JavaScript lantern draw (II). I hope this article will help you.
Articles you may be interested in:
- Javascript single-line text scroll up
- Javascript code for hover and zoom in
- Js marquee code (self-written)
- Javascript text box walking and running lantern effect code sharing
- JavaScript code for implementing the text effect of the running lantern in the status bar
- Example of a javascript Lucky Draw
- Analysis and Optimization of the code for the example of the lucky draw with JavaScript (1)