Objective Front-End JavaScript

5,124 views

Published on

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

Published in: Technology
0 Comments
12 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,124
On SlideShare
0
From Embeds
0
Number of Embeds
2,357
Actions
Shares
0
Downloads
24
Comments
0
Likes
12
Embeds 0
No embeds

No notes for slide

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. ステキ

×