Dans le dernier article, je vous ai présenté Implémentation JavaScript de l'analyse et de l'optimisation du code d'un exemple d'événement de loterie de marque (1) , car nous devons écrire un plug-in. Ensuite, quelque chose appelé « plug-in » doit avoir certaines caractéristiques qui peuvent répondre à nos besoins quotidiens de développement ou améliorer notre efficacité de développement. Alors, quelles sont les caractéristiques de base que devrait avoir ce qu’on appelle un plug-in ? Résumons :
1. Quelques fonctionnalités de base des plug-ins JavaScript :
La configuration doit être simple
Les variables définies dans le plug-in ne polluent pas les variables globales
Le même morceau de code peut être réutilisé à différents endroits
Les utilisateurs peuvent personnaliser leurs propres paramètres de fonction
A pour fonction de détruire les variables et les paramètres
Si nous écrivons un plug-in selon les caractéristiques ci-dessus, nous pouvons résumer une structure de code de base. Examinons-le un par un :
1. La configuration du plug-in doit être aussi simple que possible
Configuration des nœuds de conteneur en HTML
//这里的node-type="reward-area" 是标识我们插件的容器节点 <div class="re-area" node-type="reward-area" >
Initialisez le plug-in une fois le chargement du DOM terminé
$(function() { //这里的 test 是代表容器的 class window.LightRotate.init($('[node-type=reward-area]')); });
2. Les variables définies dans le plug-in ne polluent pas les variables globales
L'identifiant JavaScript avec une portée au niveau du bloc est une fonction. Alors comment déclarer nos variables pour qu’elles ne polluent pas les variables globales ?
Ici, nous devons utiliser la connaissance de l'auto-exécution d'une fonction JavaScript. Le code est le suivant :
(function(){ // do something })();
3. Réutiliser le code de fonction à différents endroits
Cela nous oblige à utiliser nos points de connaissances orientés objet pour résumer notre code fonctionnel en objets. Lorsque nous avons besoin de l'utiliser, nous pouvons instancier l'objet. Continuons ensuite à écrire le code dans la deuxième partie,
// (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. Les utilisateurs peuvent personnaliser les paramètres de fonction
Nous devrions d'abord avoir des paramètres par défaut, tels que les suivants
// (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);
En fait, s'ils sont écrits ainsi, les utilisateurs peuvent déjà modifier nos fichiers JavaScript pour compléter la personnalisation. Mais afin de rendre notre différence de prix facile à utiliser, par exemple, que se passe-t-il si nos utilisateurs ne comprennent pas du tout js ? ce qu'il faut faire?
De cette façon, nous pouvons configurer ces paramètres en html à l'aide d'attributs personnalisés, comme suit :
<div class="re-area" node-type="reward-area" data-setting='{ "liAutoPlay":false, "roLiSpeed":100, "roPrSpeed":200, "liDirection":true, "randomPrize":false}'>
De cette façon, les utilisateurs n'ont qu'à configurer les paramètres du conteneur actuel exécuté dans le nœud html. Cet avantage permet également à différents conteneurs sur la même page de configurer les paramètres séparément, réduisant ainsi le couplage.
Alors, comment obtenir ces paramètres en js ? Dans le code ci-dessus, il existe déjà des fonctions d'objet fonctionnel. Nous souhaitons donc étendre la méthode objet pour obtenir les paramètres personnalisés de l'utilisateur, que devons-nous faire ? Nous utilisons généralement des éléments prototypes pour étendre les méthodes de nos objets existants. Le code est le suivant :
// (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. La fonction de destruction des variables et des paramètres
La dernière est que notre plug-in devrait avoir pour fonction de détruire ses propres variables et paramètres. Comment devrions-nous l’écrire ? Ou continuez à étendre la méthode appelable de l'objet fonctionnel en fonction du code ci-dessus. Le code est le suivant :
.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; } };
À partir du contenu ci-dessus, nous pouvons comprendre à peu près les fonctions de base qu'un plug-in mature devrait avoir.
2. Exemples de développement et d'optimisation de plug-ins
Il se trouve que ce projet était un projet urgent avant les vacances de la Fête du Printemps, à cette époque, afin de rattraper le retard, je n'ai pas réfléchi en détail à la structure de mon code, ce qui offrait des opportunités d'optimisation ultérieure. de moi-même.
D'après le contenu du timer présenté dans la section précédente, nous pouvons savoir que JavaScript est monothread. Alors
Si un morceau de code s'exécute de manière très inefficace, cela affectera l'exécution du code suivant. Donc pour JavaScript, l’optimisation du code est indispensable.
Voyons d'abord quelles fonctions notre plug-in « marquee » devrait avoir :
Être capable de contrôler si les lumières fonctionnent automatiquement
Le sens de rotation de la lumière peut être contrôlé
La vitesse de rotation de la lumière peut être contrôlée
La vitesse de rotation du prix peut être contrôlée
Le processus de développement de ces points de fonction ne sera pas présenté en détail ici, seul le processus d'optimisation sera introduit. Si vous êtes intéressé, vous pouvez voir l'adresse du code source ci-jointe à la fin de mon article pour télécharger et lire.
1. Optimisation de l'acquisition "séquentielle" du code du gyrophare
Parce que j'utilise le positionnement absolu pour les lumières environnantes, je dois obtenir leur liste "séquentiellement" puis opérer.
Récupérez d’abord le nœud DOM.
//获取外围的灯,可以看到我这里使用的选择器多了一个 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');
Ensuite, la liste des éléments DOM du nœud "light" doit être obtenue "séquentiellement".
Ma première version est comme ceci :
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]); }
Parce que les lumières dans les directions « bas » et « gauche » doivent être dans l'ordre inverse, j'ai utilisé deux boucles for dans l'ordre inverse. En fait, lorsque des boucles apparaissent, nous devrions tous nous demander s'il y a de la place pour l'optimisation. dans notre code.
Le code optimisé ressemble à ceci, ici j'ai réduit l'utilisation de 4 boucles
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实现跑马灯抽奖活动实例代码解析与优化(二)的相关知识就给大家介绍到这里,希望本文所述对大家有所帮助。