Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Objective Front-End JavaScript

5,566 views

Published on

JavaScript祭スピンオフ! フロントエンド祭り in Co-Edo での発表資料です

Published in: Technology
  • Be the first to comment

Objective Front-End JavaScript

  1. 1. Objective Front-End JavaScript
  2. 2. 自己紹介 me = { name: "muyuu", twitter: "@anticyborg", belongs: "freelance", job: "Web Front-End Engineer" };
  3. 3. jQuery plugin
  4. 4. GOOD • 早い • 簡単 • 何だったらJS書けなくても何とかなる
  5. 5. BAD • 変更に弱い • プラグインにない機能を求められると詰む • いつまで経ってもJS覚えられない 割と辛い思いをすることも多い
  6. 6. 自分で作る
  7. 7. BAD • 面倒 • 果たして望む機能を作れるのか • プラグインみたいにすげーの作れるのか
  8. 8. GOOD • すげーのはいらない。必要な機能だけあれば良い • 追加機能が欲しくなったらその時足せば良い • 変更時も理解しやすい(理解しやすいように書けば)
  9. 9. GOOD • すげーのはいらない。必要な機能だけあれば良い • 追加機能が欲しくなったらその時足せば良い • 変更時も理解しやすい(理解しやすいように書けば) JSの理解も深まるよ!
  10. 10. いいことだらけ
  11. 11. さぁ作ろう いま作ろう
  12. 12. 今回作るもの
  13. 13. Tab
  14. 14. 何も考えずにタブを実装
  15. 15. $(function() { // 最初の要素以外は非表示 $(".body li").not(":first").hide(); $(".tab a").click(function(){ // 表示するコンテンツのIDを取得 var target = $(this).attr("href").replace("#", ""); // コンテンツ部分を全部隠す $(".body li").hide(); // クリックしたタブのhretと同じIDを持つ箇所だけを表示する $(".body").find('#' + target).show(); return false; }); });
  16. 16. problemas
  17. 17. パターンが増える度に コードが倍増
  18. 18. $(function() { // アニメーションするパターン $(".body2 li").not(":first").hide(); $(".tab2 a").click(function(){ var target = $(this).attr("href").replace("#", ""); $(".body2 li").hide('slow'); $(".body2").find('#' + target).show('slow'); return false; }); // ページ表示時は2つ目が開いてるパターン $(".body3 li").not(":first").hide(); $(".tab3 a").click(function(){ var target = $(this).attr("href").replace("#", ""); $(".body3 li").hide('slow'); $(".body3").find('#' + target).show('slow'); return false; }); });
  19. 19. solution
  20. 20. 解決法 • タブの原型となるオブジェクトを作る • 原型を元に実体を生成する • 実体はパターン毎に生成する
  21. 21. object
  22. 22. オブジェクトとは、名前 と値を持つプロパティを 格納するコンテナにすぎ ない — 開眼!JavaScript
  23. 23. object sample // コンストラクタ関数を使用して僕オブジェクトを生成 var muyuu = new Object(); //僕オブジェクトにプロパティを追加 muyuu.name = "muyuu"; muyuu.age = 33; muyuu.gender = "male"; console.log(muyuu.age); // 33 と表示される
  24. 24. object sample //オブジェクトに関数を追加する muyuu.hello = function(){ console.log("Hello! I'm " + muyuu.name); }; muyuu.hello(); // "Hello! I'm muyuu" と表示される • プロパティが関数の場合は「メソッド」とも呼ばれる
  25. 25. コンストラクタ関数?
  26. 26. コンストラクタ関数 コンストラクタ関数とは、あらかじめ決められたオブジェクト を生成するテンプレート、クッキーの抜き型のようなものだと 思ってください — 開眼!JavaScript
  27. 27. コンストラクタ関数 var obj = new Object(); // オブジェクトを変数objに生成 var num = new Number(123); // 数値オブジェクトを変数numに生成 var str = new String('aaa'); // 文字列オブジェクトを変数strに生成
  28. 28. コンストラクタ関数 こんな感じのが実装されている Object = function(){ //新しいオブジェクトを作るための処理 };
  29. 29. コンストラクタ関数で 独自オブジェクトを作る
  30. 30. コンストラクタ関数 僕オブジェクトのテンプレートとして人コンストラクタを作る var Human = function(name, age, gender){ this.name = name; this.age = age; this.gender = gender; this.hello = function (){ console.log("Hello! I'm " + this.name); }; };
  31. 31. コンストラクタ関数 人コンストラクタで僕オブジェクトを作成 // Humanコンストラクタを使用して僕オブジェクトを生成 // 生成する際に僕のデータを引数で渡してあげれば // コンストラクタの設定通りに生成される var muyuu = new Human("muyuu", 33, "male"); // 挨拶をする muyuu.hello(); // Hello! I'm muyuu と表示される
  32. 32. ちょっと寄り道して も1歩深く
  33. 33. 通常の関数の挙動 • 関数は通常、何かしらの処理をして何かしらの値を返す • 何もreturnしない場合はfalse相当の値を返す
  34. 34. //return がある関数 function add(a,b){ return a + b; } console.log(add(1, 2)); // 3 // return がない関数 function alertAdd(a, b){ var add = a + b; } console.log(alertAdd()); // undefined
  35. 35. コンストラクタ関数の挙動 • オブジェクトを返している var muyuu = new Human("muyuu", 33, "male"); console.log(muyuu); // { // name:"muyuu", // age:33, // gender: "male", // hello: function // }
  36. 36. Why?
  37. 37. new 演算子 • 関数はnew演算子を使って呼び出された場合、コンストラク タ関数のthisの値として、生成されたオブジェクトとして設定 する • new演算子を使って呼び出された場合にreturnを宣言してい ない場合は通常falseを返すところを新たに生成されるオブジ ェクト(this)を返すようになる
  38. 38. new 演算子 var Human = function(name, age, gender){ //new演算子で呼び出した場合、実はこの処理が入っている // var this = new Object(); this.name = name; this.age = age; ... //new演算子で呼び出し、returnを行っていない場合 //実はthisを返している //return this; };
  39. 39. 閑話休題
  40. 40. タブコンストラクタ作って パターン毎に生成するぜ!
  41. 41. タブの実装に必要な機能 コンストラクタ呼び出し時に以下を指定 • タブのルートのクラス • タブ部分のクラス • コンテンツ部分のクラス
  42. 42. タブの実装に必要な機能 必要な機能 *今表示している要素の番号(何番目) *今表示している要素が何番目かを知る機能 *タブを切り替える機能 *タブ切り替え時にクラスを付与する機能
  43. 43. コンストラクタを作成 // constructor var Tab = function(param){ }; Tabコンストラクタを作成
  44. 44. コンストラクタ呼び出し時 var tab1 = new Tab({ root: ".tab", // タブのルート要素を指定 item: ".tabHead li", // タブ部分の他所を指定 body: ".tabBody li" // コンテンツ部分の他所を指定 }); コンストラクタ関数呼び出し時に、実際ページあるタブの要素 を新たに作るオブジェクトに設定するため、オプションとして オブジェクトを渡す。
  45. 45. コンストラクタを作成 var Tab = function(param){ this.$root = $(param.root); this.$item = this.$root.find(param.item); this.$body = this.$root.find(param.body); ... }; コンストラクタ実行時に渡された引数からjQueryオブジェクト を保存
  46. 46. コンストラクタを作成 var Tab = function(param){ ... //カレントのタブとコンテンツに付与するclassを設定 this.adClass = 'current'; // カレントのコンテンツが何番目かを保存する変数を作成 this.currentIndex; ... };
  47. 47. コンストラクタを作成 var Tab = function(param){ this.param = param // オプションを追加 ... };
  48. 48. コンストラクタを作成 var Tab = function(param){ ... this.init(); //ページ表示時に実行した処理を実行 //タブをクリックした際の挙動を設定 var self = this; // alias this.$item.on("click", "a", function(){ self.setCurrent(this); // カレントをセット self.change(); // タブを切り替え }); };
  49. 49. コンストラクタを作成 // constructor var Tab = function(param){ this.param = param; this.$root = $(param.root); this.$item = this.$root.find(param.item); this.$body = this.$root.find(param.body); this.adClass = 'current'; // class this.currentIndex = 0; // current tab index this.init(); // 初期化 var self = this; // alias this.$item.on("click", "a", function(){ // evnet self.setCurrent(this); self.change(); }); };
  50. 50. 必要な機能をコンストラクタに追加 ページ表示時に実行する関数 Tab.prototype.init = function(){ this.setCurrent(); // カレントをセット this.change(); // タブを切り替え };
  51. 51. 必要な機能をコンストラクタに追加 カレントが何番目かを取得する関数 Tab.prototype.setCurrent = function(ele){ this.currentIndex = 0; if (ele){ // 引数がタブの何番目の要素かを取得 var index = $(ele).parent().index(); // オブジェクト変数にセット this.currentIndex = index; } };
  52. 52. 必要な機能をコンストラクタに追加 タブを切り替える関数 Tab.prototype.change = function(){ this.changeTab(); // タブ部分を変更 this.changeBody(); // コンテンツ部分を変更 };
  53. 53. 必要な機能をコンストラクタに追加 タブ部分の変更処理をまとめた関数 Tab.prototype.changeTab = function(){ this.$item .removeClass(this.adClass) // 全部のタブからクラスを外して .eq(this.currentIndex) // カレントのタブのみ .addClass(this.adClass); // クラスを付与する };
  54. 54. 必要な機能をコンストラクタに追加 コンテンツ部分の変更処理をまとめた関数 Tab.prototype.changeBody = function(){ this.$body .removeClass(this.adClass) // 全部のコンテンツからクラスを外して .hide() // 非表示にして .eq(this.currentIndex) // カレントのコンテンツのみ .addClass(this.adClass) // クラスを付与して .show(); // 表示する };
  55. 55. 完成
  56. 56. 後は必要な機能を 必要になったら足すだけ
  57. 57. コンテンツの表示で アニメーション足したい
  58. 58. 該当関数を変更するだけ Tab.prototype.changeBody = function(){ this.$body .removeClass(this.adClass) // 全部のコンテンツからクラスを外して .hide('slow') // 非表示にして .eq(this.currentIndex) // カレントのコンテンツのみ .addClass(this.adClass) // クラスを付与して .show('slow'); // 表示する };
  59. 59. アニメーションは オプションにしたい
  60. 60. 呼び出し時にオプションを追加 var tab1 = new Tab({ root: ".tab", // タブのルート要素を指定 item: ".tabHead li", // タブ部分の他所を指定 body: ".tabBody li", // コンテンツ部分の他所を指定 duration: true // アニメーションの指定 });
  61. 61. オプションによって挙動を変える Tab.prototype.changeBody = function(){ this.$body .removeClass(this.adClass) // 全部のコンテンツからクラスを外して .hide(param.duration) // 非表示にして .eq(this.currentIndex) // カレントのコンテンツのみ .addClass(this.adClass) // クラスを付与して .show(param.duration); // 表示する };
  62. 62. 呼び出し var tab1 = new Tab({ root: ".tab", // タブのルート要素を指定 item: ".tabHead li", // タブ部分の他所を指定 body: ".tabBody li", // コンテンツ部分の他所を指定 }); var tab2 = new Tab({ root: ".otherTab", // タブのルート要素を指定 item: ".otherTabHead .tab", // タブ部分の他所を指定 body: ".otherTabBody .content", // コンテンツ部分の他所を指定 duration: 400 });
  63. 63. ステキ

×