なんてあやふやなタイトルなんや・・。
例えばタブのUIとか、簡単ですがライブラリちっくなものを書く機会が最近多いです。
そんなとき、オブジェクト作って全部やるパターンと、Functionで作ってnewして使うパターンと、結局どっちが良いんやろ?って思ったんです。
あと、他にも思うところがあったので、やっつけ仕事で2パターン書いてみて考察。
というわけでタブのUI
HtmlとCssは共通のものを使います。
Html/Css
<!DOCTYPE HTML> <html lang="ja-JP"> <head> <meta charset="UTF-8"> <title>Tab lib</title> <style> /* For css */ .my-tab-container .my-tab-header { display: -webkit-box; list-style: none; padding: 0; background-color: #eee; text-align: center; } .my-tab-container .my-tab-header li { -webkit-box-flex: 1; } .my-tab-container .my-tab-header .js-active { background-color: #000; color: #fff; } .my-tab-container .my-tab-body { padding: 0; } /* For js */ .js-tab-container .js-tab-header .js-active { pointer-events: none; } .js-tab-container .js-tab-body li { display: none; } .js-tab-container .js-tab-body .js-active { display: block; } </style> </head> <body> <div class="js-tab-container my-tab-container"> <ul class="js-tab-header my-tab-header"> <li>Title1</li> <li>Title2</li> <li>Title3</li> </ul> <ul class="js-tab-body my-tab-body"> <li>Text1 is this. JavaScript is really difficult and ...</li> <li>Text2 is this. JavaScript is really difficult and ...</li> <li>Text3 is this. JavaScript is really difficult and ...</li> </ul> </div> <script src="//cdnjs.cloudflare.com/ajax/libs/zepto/1.0/zepto.min.js"></script> <!-- ここでそれぞれjsを読み込んで実行 --> </body> </html>
Javascript
まずはそれぞれのソース。
今回はZepto.jsを使ってみた。
Objectパターン
// Act like "tab-obj.js" file. ;(function(global, $, undefined) { 'use strict'; var classNames = { header: '.js-tab-header', body: '.js-tab-body', active: 'js-active' // for addClass! Dont prepend ".". }; var Tab = { trigger: $(classNames.header).find('li'), body: $(classNames.body).find('li'), init: function() { Tab.showThis(Tab.trigger.eq(0)); Tab.trigger.on('click', Tab.showThis); }, showThis: function(e) { var index = Tab.trigger.index(e.target), c = classNames; Tab._refresh(); Tab.trigger.eq(index).addClass(c.active); Tab.body.eq(index).addClass(c.active); }, _refresh: function() { var c = classNames; Tab.trigger.removeClass(c.active); Tab.body.removeClass(c.active); } }; global.Tab = Tab; }(this.self || global, Zepto));
実行する時は、
;(function(global, $, undefined) { 'use strict'; global.Tab.init(); }(this.self || global, Zepto));
Functionパターン
// Act like "tab-func.js" file. ;(function(global, $, undefined) { 'use strict'; var classNames = { header: '.js-tab-header', body: '.js-tab-body', active: 'js-active' // for addClass! Dont prepend ".". }; var Tab = function($elm) { this.init($elm); }; Tab.prototype.init = function($elm) { var that = this, c = classNames; that.trigger = $elm.find(c.header).find('li'); that.body = $elm.find(c.body).find('li'); that.trigger.on('click', $.proxy(this.showThis, this)); that.showThis(that.trigger.eq(0)); }; Tab.prototype.showThis = function(e) { var that = this, c = classNames, index = that.trigger.index(e.target); that._refresh(); that.trigger.eq(index).addClass(c.active); that.body.eq(index).addClass(c.active); }; Tab.prototype._refresh = function() { var that = this, c = classNames; that.trigger.removeClass(c.active); that.body.removeClass(c.active); }; global.Tab = Tab; }(this.self || global, Zepto));
実行する時は、
;(function(global, $, undefined) { 'use strict'; new global.Tab($('.js-tab-container')); }(this.self || global, Zepto));
結局どっちがいいのか
良いと思ったところを列挙。
Objectパターン
- 記述もわかりやすいので、実装するのが楽。
- コードが短い!(本質的には同じでも、印象として)
Functionパターン
- プロトタイプ活用って省メモリぽい。
- 拡張しやすい!(1ページにタブが2つ以上ある時とか)
- クラス名などを引数で渡せるので柔軟性がある。
やっぱり・・・基本的にやれることは同じやと思うので、その時々で使い分けるしかないかしら。
クラス名決め打ちでも問題ないものや、そのページでしか使わんやろ!みたいな汎用性の低いUIについてはObjectパターンで決め打ちで。
それ以外は基本的にFunctionパターンで作れば良いって感じかな・・?