Im letzten Artikel habe ich Ihnen JavaScript-Implementierung der Beispielcodeanalyse und -optimierung für Festzelt-Lotterieereignisse (1) vorgestellt, da wir ein Plug-in schreiben müssen. Dann muss ein sogenanntes „Plug-In“ bestimmte Eigenschaften aufweisen, die unseren täglichen Entwicklungsanforderungen gerecht werden oder unsere Entwicklungseffizienz verbessern können. Was sind also die grundlegenden Eigenschaften, die ein sogenanntes Plug-In haben sollte? Fassen wir es zusammen:
1. Einige grundlegende Funktionen von JavaScript-Plugins:
Die Konfiguration muss einfach sein
Im Plug-in definierte Variablen verschmutzen keine globalen Variablen
Derselbe Code kann an verschiedenen Stellen wiederverwendet werden
Benutzer können ihre eigenen Funktionsparameter anpassen;
Hat die Funktion, Variablen und Parameter zu zerstören;
Wenn wir ein Plug-In gemäß den oben genannten Merkmalen schreiben, können wir eine grundlegende Codestruktur zusammenfassen. Schauen wir uns diese einzeln an:
1. Die Plug-in-Konfiguration sollte so einfach wie möglich sein
Containerknoten in HTML konfigurieren
//这里的node-type="reward-area" 是标识我们插件的容器节点 <div class="re-area" node-type="reward-area" >
$(function() { //这里的 test 是代表容器的 class window.LightRotate.init($('[node-type=reward-area]')); });
JavaScripts Bezeichner mit Gültigkeitsbereich auf Blockebene ist die Funktion. Wie deklarieren wir also unsere Variablen, damit sie globale Variablen nicht verschmutzen? Hier müssen wir das Wissen über die Selbstausführung einer JavaScript-Funktion nutzen. Der Code lautet wie folgt:
(function(){ // do something })();
Dies erfordert, dass wir unsere objektorientierten Wissenspunkte verwenden, um unseren Funktionscode in Objekte zu abstrahieren. Wenn wir ihn verwenden müssen, können wir das Objekt instanziieren. Dann schreiben wir den Code im zweiten Teil weiter,
// (function($){ // 创建功能对象 var LightRotate = function (select) { // do something }; LightRotate.init = function (select) { var _this = this; //根据不同的容器实例化不同的对象 select.each(function () { new _this($(this)); }); }; window.LightRotate = LightRotate; })(jQuery);
Zuerst sollten wir Standardparametereinstellungen haben, wie zum Beispiel die folgenden
// (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);
<div class="re-area" node-type="reward-area" data-setting='{ "liAutoPlay":false, "roLiSpeed":100, "roPrSpeed":200, "liDirection":true, "randomPrize":false}'>
// (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);
Der letzte Punkt ist, dass unser Plug-in die Funktion haben sollte, seine eigenen Variablen und Parameter zu zerstören. Wie sollen wir es schreiben? Oder erweitern Sie die aufrufbare Methode des Funktionsobjekts basierend auf dem obigen Code. Der Code lautet wie folgt:
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; } };
2. Plug-in-Entwicklungs- und Optimierungsbeispiele
Zufälligerweise war dieses Projekt vor den Frühlingsfestferien ein dringendes Projekt. Um den Zeitplan einzuhalten, dachte ich nicht im Detail über meine Codestruktur nach, was Möglichkeiten für eine spätere Optimierung bot von mir selbst.
Aus dem Inhalt des im vorherigen Abschnitt eingeführten Timers können wir erkennen, dass JavaScript Single-Threaded ist. AlsoWenn ein Codeabschnitt sehr ineffizient ausgeführt wird, wirkt sich dies auf die Ausführung des nachfolgenden Codes aus. Für JavaScript ist die Codeoptimierung daher ein Muss.
Schauen wir uns zunächst an, welche Funktionen unser „Marquee“-Plugin haben soll:
Sie können steuern, ob die Lichter automatisch eingeschaltet werden
Die Drehrichtung des Lichts kann gesteuert werden;
Die Rotationsgeschwindigkeit des Lichts kann gesteuert werden;
Die Rotationsgeschwindigkeit des Preises kann gesteuert werden;
Der Entwicklungsprozess dieser Funktionspunkte wird hier nicht im Detail vorgestellt, sondern nur der Optimierungsprozess. Wenn Sie interessiert sind, können Sie die Quellcodeadresse am Ende meines Artikels herunterladen und lesen.
1. Optimierung der „sequenziellen“ Erfassung rotierender Lichtcodes
Da ich die absolute Positionierung für die Umgebungslichter verwende, muss ich deren Liste „sequentiell“ abrufen und dann arbeiten.
Besorgen Sie sich zuerst den DOM-Knoten.
Dann sollte die Liste der DOM-Elemente des „light“-Knotens „sequentiell“ abgerufen werden.
Meine erste Version sieht so aus:
//获取外围的灯,可以看到我这里使用的选择器多了一个 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');
Da die Lichter in der Richtung „unten“ und „links“ in umgekehrter Reihenfolge sein müssen, habe ich zwei for-Schleifen in umgekehrter Reihenfolge verwendet. Tatsächlich sollten wir alle darüber nachdenken, ob es Raum für Optimierung gibt in unserem Code.
Der optimierte Code sieht so aus, hier habe ich die Verwendung von 4 Schleifen reduziert
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]); }
列表倒序我使用了原生 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实现跑马灯抽奖活动实例代码解析与优化(二)的相关知识就给大家介绍到这里,希望本文所述对大家有所帮助。