Dalam artikel lepas, saya memperkenalkan anda kepada Pelaksanaan JavaScript analisis dan pengoptimuman contoh kod acara loteri marquee (1) , kerana kita perlu menulis pemalam. Kemudian sesuatu yang dipanggil "plug-in" mesti mempunyai ciri-ciri tertentu yang boleh memenuhi keperluan pembangunan harian kita atau meningkatkan kecekapan pembangunan kita. Jadi apakah ciri asas yang perlu ada pada sesuatu yang dipanggil pemalam? Mari kita ringkaskan:
1. Beberapa ciri asas pemalam JavaScript:
Tatarajah mestilah mudah
Pembolehubah yang ditakrifkan dalam pemalam tidak mencemarkan pembolehubah global
Sekeping kod yang sama boleh digunakan semula di tempat yang berbeza;
Pengguna boleh menyesuaikan parameter fungsi mereka sendiri
Mempunyai fungsi memusnahkan pembolehubah dan parameter;
Jika kita menulis pemalam mengikut ciri di atas, kita boleh meringkaskan struktur kod asas Mari kita lihat satu persatu:
Mengkonfigurasi nod bekas dalam html
//这里的node-type="reward-area" 是标识我们插件的容器节点 <div class="re-area" node-type="reward-area" >
$(function() { //这里的 test 是代表容器的 class window.LightRotate.init($('[node-type=reward-area]')); });
Pengecam JavaScript dengan skop peringkat blok ialah fungsi. Jadi bagaimana kita mengisytiharkan pembolehubah kita supaya ia tidak mencemarkan pembolehubah global?
Di sini kita perlu menggunakan pengetahuan tentang pelaksanaan sendiri fungsi JavaScript. Kodnya adalah seperti berikut:
(function(){ // do something })();
Ini memerlukan kami menggunakan mata pengetahuan berorientasikan objek untuk mengabstrak kod fungsi kami menjadi objek Apabila kami perlu menggunakannya, kami boleh membuat instantiat objek. Kemudian mari teruskan menulis kod di bahagian kedua,
// (function($){ // 创建功能对象 var LightRotate = function (select) { // do something }; LightRotate.init = function (select) { var _this = this; //根据不同的容器实例化不同的对象 select.each(function () { new _this($(this)); }); }; window.LightRotate = LightRotate; })(jQuery);
Mula-mula kita harus mempunyai tetapan parameter lalai, seperti yang berikut
// (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}'>
Jadi bagaimana kita boleh mendapatkan parameter ini dalam js? Dalam kod di atas, sudah ada fungsi objek berfungsi. Jadi kami ingin melanjutkan kaedah objek untuk mendapatkan parameter tersuai pengguna, apakah yang perlu kami lakukan? Kami biasanya menggunakan perkara prototaip untuk memanjangkan kaedah objek sedia ada kami adalah seperti berikut:
// (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);
Yang terakhir ialah pemalam kami sepatutnya mempunyai fungsi memusnahkan pembolehubah dan parameternya sendiri. Bagaimana kita harus menulisnya? Atau teruskan memanjangkan kaedah boleh panggil objek berfungsi berdasarkan kod di atas Kodnya adalah seperti berikut:
Daripada kandungan di atas, kita boleh memahami secara kasar fungsi asas yang perlu ada pada pemalam matang.
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; } };
Kebetulan projek ini adalah projek mendesak sebelum cuti Festival Musim Bunga Pada masa itu, untuk mengejar jadual, saya tidak memikirkan struktur kod saya secara terperinci, yang memberikan peluang untuk pengoptimuman seterusnya. daripada diri saya sendiri. Daripada kandungan pemasa yang diperkenalkan di bahagian sebelumnya, kita boleh tahu bahawa JavaScript adalah satu benang. Jadi
Jika sekeping kod berjalan dengan sangat tidak cekap, ia akan menjejaskan pelaksanaan kod berikutnya. Jadi untuk JavaScript, pengoptimuman kod adalah satu kemestian.
Mari kita lihat dahulu apakah fungsi pemalam "marquee" kami:Dapat mengawal sama ada lampu dimainkan secara automatik
Arah putaran cahaya boleh dikawal
Kelajuan putaran cahaya boleh dikawal
Proses pembangunan titik fungsi ini tidak akan diperkenalkan secara terperinci di sini, hanya proses pengoptimuman akan diperkenalkan. Jika anda berminat, anda boleh lihat alamat kod sumber yang dilampirkan di penghujung artikel saya untuk dimuat turun dan dibaca.
1. Pengoptimuman pemerolehan "berurutan" kod lampu berputar
Oleh kerana saya menggunakan kedudukan mutlak untuk lampu sekeliling, saya perlu mendapatkan senarainya "berurutan" dan kemudian beroperasi. Mula-mula dapatkan nod DOM.
Kemudian senarai elemen DOM nod "cahaya" hendaklah diperolehi "berurutan".
//获取外围的灯,可以看到我这里使用的选择器多了一个 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');
Oleh kerana lampu dalam arah "bawah" dan "kiri" perlu dalam susunan terbalik, saya menggunakan dua untuk gelung dalam susunan terbalik Malah, apabila gelung muncul, kita semua harus memikirkan sama ada terdapat ruang untuk pengoptimuman dalam kod kami.
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实现跑马灯抽奖活动实例代码解析与优化(二)的相关知识就给大家介绍到这里,希望本文所述对大家有所帮助。