ホームページ > ウェブフロントエンド > jsチュートリアル > マーキー宝くじイベントのJavaScript実装サンプルコード分析と最適化(2)_JavaScriptスキル

マーキー宝くじイベントのJavaScript実装サンプルコード分析と最適化(2)_JavaScriptスキル

WBOY
リリース: 2016-05-16 15:15:29
オリジナル
1260 人が閲覧しました

前回の記事では、プラグインを書く必要があるため、マーキー宝くじイベントのJavaScript実装サンプルコード分析と最適化(1)を紹介しました。その場合、「プラグイン」と呼ばれるものは、日常の開発ニーズを満たしたり、開発効率を向上させたりできる特定の特性を備えている必要があります。では、プラグインと呼ばれるものが持つべき基本的な特性は何でしょうか?要約しましょう:

1. JavaScript プラグインのいくつかの基本機能:

構成はシンプルである必要があります
プラグインで定義された変数はグローバル変数を汚染しません。 同じコード部分を別の場所で再利用できます
ユーザーは独自の関数パラメータをカスタマイズできます。 変数とパラメータを破棄する機能があります。
上記の特性に従ってプラグインを作成すると、基本的なコード構造を 1 つずつ見てみましょう。

1. プラグインの設定はできるだけシンプルにする必要があります

HTML でのコンテナ ノードの構成

//这里的node-type="reward-area" 是标识我们插件的容器节点
<div class="re-area" node-type="reward-area" >
ログイン後にコピー
DOM の読み込みが完了したらプラグインを初期化します

$(function() {
//这里的 test 是代表容器的 class
window.LightRotate.init($('[node-type=reward-area]'));
});
ログイン後にコピー
2. プラグインで定義された変数はグローバル変数を汚染しません

ブロックレベルのスコープを持つ JavaScript の識別子は function です。では、グローバル変数を汚染しないように変数を宣言するにはどうすればよいでしょうか?

ここでは、JavaScript 関数の自己実行に関する知識を使用する必要があります。コードは次のとおりです:


(function(){
// do something
})();
ログイン後にコピー
3. 関数コードを別の場所で再利用する

これには、オブジェクト指向のナレッジ ポイントを使用して、関数コードをオブジェクトに抽象化し、それを使用する必要があるときにオブジェクトをインスタンス化する必要があります。次に、2 番目の部分

でコードを書き続けましょう。

//
(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. ユーザーは関数パラメータをカスタマイズできます

まず、次のようなデフォルトのパラメータ設定が必要です。

//
(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);
ログイン後にコピー
実際、このように記述すると、ユーザーはすでに JavaScript ファイルを変更してカスタマイズを完了することができます。しかし、価格差を使いやすくするために、たとえばユーザーが js をまったく理解していない場合はどうなるでしょうか?何をするか?
このようにして、次のようにカスタム属性を使用して HTML でこれらのパラメーターを構成できます。


この方法では、ユーザーは HTML ノードで実行されている現在のコンテナのパラメータを設定するだけで済みます。この利点により、同じページ上の異なるコンテナがパラメータを個別に設定できるようになり、結合が軽減されます。
<div class="re-area" node-type="reward-area" data-setting='{
"liAutoPlay":false,
"roLiSpeed":100,
"roPrSpeed":200,
"liDirection":true,
"randomPrize":false}'>
ログイン後にコピー
では、js でこれらのパラメータを取得するにはどうすればよいでしょうか?上記のコードには、すでに機能オブジェクト関数が存在します。したがって、オブジェクト メソッドを拡張してユーザーのカスタム パラメータを取得したいのですが、どうすればよいでしょうか?通常、既存のオブジェクトのメソッドを拡張するにはプロトタイプのものを使用します。コードは次のとおりです。

5. 変数とパラメータを破棄する関数。
//
(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);
ログイン後にコピー
最後の 1 つは、プラグインには独自の変数とパラメーターを破棄する機能が必要であるということです。どのように書けばよいのでしょうか?または、上記のコードに基づいて関数オブジェクトの呼び出し可能なメソッドを拡張し続けると、コードは次のようになります。

上記の内容から、成熟したプラグインが備えるべき基本的な機能を大まかに理解できます。

2. プラグインの開発と最適化の例
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;
}
};
ログイン後にコピー
たまたまこのプロジェクトは春節休暇前の緊急プロジェクトだったので、その時はスケジュールを守るためにコード構造について詳しく考えず、その後の最適化の機会となりました。私自身の。

前のセクションで紹介したタイマーの内容から、JavaScript がシングルスレッドであることがわかります。ということで

コードの一部が非常に非効率的に実行されると、後続のコードの実行に影響します。したがって、JavaScript の場合、コードの最適化は必須です。 まず、「マーキー」プラグインにどのような機能が必要かを見てみましょう:

ライトを自動的に再生するかどうかを制御できます。

ライトの回転方向を制御できます。

ライトの回転速度は制御可能です。

賞品の回転速度を制御できます。

これらのファンクション ポイントの開発プロセスについてはここでは詳しく紹介せず、最適化プロセスのみを紹介します。興味があれば、記事の最後にソース コードのアドレスが添付されているので、ダウンロードして読むことができます。

1. 回転光コードの「逐次」取得の最適化


周囲のライトに絶対位置を使用しているため、それらのリストを「順番に」取得してから操作する必要があります。

まず、DOM ノードを取得します。

次に、「ライト」ノードの 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');
ログイン後にコピー

「下」と「左」の方向のライトは逆の順序にする必要があるため、2 つの for ループを逆の順序で使用しました。実際、ループが出現するときは、最適化の余地があるかどうかを全員が考慮する必要があります。私たちのコードでは。

最適化されたコードは次のようになります。ここでは 4 つのループの使用を減らしています

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实现跑马灯抽奖活动实例代码解析与优化(二)的相关知识就给大家介绍到这里,希望本文所述对大家有所帮助。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート