Top Banner
knockout.jsknockoutされた話 2014/02/28 Fukuoka Frontend Frogs Ex Hiroyuki Tashima
98

Knocked out in knockout js

May 11, 2015

Download

Technology

It was knocked out in knockout.js

in Using knockout.js, i made a lot of mistakes.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Knocked out in knockout js

knockout.jsにknockoutされた話

2014/02/28  Fukuoka  Frontend  Frogs  Ex Hiroyuki  Tashima

Page 2: Knocked out in knockout js

“GGoodd ffiigghhtt oonn tthhee ssiiddee wwiitthh tthhee bbeesstt FFrraammeewwoorrkk..”

-- NNaappoolleeoonn BBoonnaappaarrttee

神は最高のフレームワークを使う側に味方する

-  ナポレオン・ボナパルト

Page 3: Knocked out in knockout js

まずはじめに

Page 4: Knocked out in knockout js

は?誰?

Page 5: Knocked out in knockout js

田島寛之

【自己紹介】

fb hiroyuki.tashima

・日本唐揚協会公認カラアゲニスト  ・株式会社gumi  West  ・フロントエンドエンジニア  

@HiroyukiTashima

Page 6: Knocked out in knockout js

knockout.jsにknockoutされた話

Page 7: Knocked out in knockout js

なぜ

knockout.js  ?

Page 8: Knocked out in knockout js

まずはこちらを

ご覧いただきたい

(・ワ・) :  福岡出張中のHさん(仮)

たしま:(・ε・)

Page 9: Knocked out in knockout js

たしまさん、knockout.jsってフレームワーク

使いませんか?

(・ワ・)

Page 10: Knocked out in knockout js

ア、イイデスネー > (・ε・)

Page 11: Knocked out in knockout js

knockout.jsだとかなりコード量減って

いい感じになりますよ〜

(・ワ・)

Page 12: Knocked out in knockout js

ア、イイデスネー > (・ε・)

Page 13: Knocked out in knockout js

たしまさんって何かフレームワーク使ってます?(・ワ・)

Page 14: Knocked out in knockout js

ア、イイデスネー > (・ε・)

Page 15: Knocked out in knockout js

要約

Page 16: Knocked out in knockout js

表示物、データ多い

Page 17: Knocked out in knockout js

表示物、データ多い

DOM操作も多い

Page 18: Knocked out in knockout js

表示物、データ多い

DOM操作も多い

js長くなる

Page 19: Knocked out in knockout js

表示物、データ多い

DOM操作も多い

js長くなる

(´・ω・`)わけわかめ

Page 20: Knocked out in knockout js

よわい(確信)

Page 21: Knocked out in knockout js

表示物、データ多い

Page 22: Knocked out in knockout js

表示物、データ多い

DOM操作も多い

Page 23: Knocked out in knockout js

表示物、データ多い

DOM操作も多い

knockout.jsを使う

Page 24: Knocked out in knockout js

表示物、データ多い

DOM操作も多い

knockout.jsを使う

コード量:減 動作:軽

Page 25: Knocked out in knockout js

つよい(確信)

Page 26: Knocked out in knockout js

で、knockout.jsを使うことに…

Page 27: Knocked out in knockout js

knockout.jsとは?

そもそも

Page 28: Knocked out in knockout js

knockout.jsとは?knockout.jsは

データモデルを基盤とし、リッチなUI構築を行う目的で開発された

JavaScriptライブラリである。

Page 29: Knocked out in knockout js

wikipediaのコピペを貼るんじゃあないよ!

> (・ε・#)

Page 30: Knocked out in knockout js

 knockout.js・UI用JavaScriptライブラリ

・jQuery等の別ライブラリとぶつからない

・MVVM(Model,  View,  ViewModel)

・DOM操作に関するコードがほぼいらない

・軽い(動作、容量)

Page 31: Knocked out in knockout js

 knockout.js

 3大ポイント 

Page 32: Knocked out in knockout js

 knockout.js

・MVVM

 Model  :  Ajaxから受け取ったデータ

 View  :  HTML

 ViewModel  :  ページ内で一時的に使用、変更するデータ

Page 33: Knocked out in knockout js

 knockout.js

・View(HTML)からbind指定

 click,  style,  css,  attr,  …

Page 34: Knocked out in knockout js

 knockout.js・常に変数の変化を監視(observable)

Page 35: Knocked out in knockout js

概要だけじゃよく分からんすなぁ

> (・ε・)

Page 36: Knocked out in knockout js

使用例

Page 37: Knocked out in knockout js

テキスト入力  +  ボタンclick  

 window  &  テキスト表示

 ↓

Page 38: Knocked out in knockout js

つまり

テキスト入力

ボタンclick

Page 39: Knocked out in knockout js

こうなる

テキスト表示ウィンドウ表示

Page 40: Knocked out in knockout js

knockout.jsを使わない場合

Page 41: Knocked out in knockout js

<div  id="main">                  <input  type="text"  id="inputForm"></input>                  <buKon  onclick="openPopup()">  o  p  e  n  </buKon>  </div>  <div  id="popup"  style="display:none">          <div  style="opacity:1;">                  <font  color="#ffffff">popupWindow</font><br  />                  <div  style="color:#ffffff;">input.value  :                            <span  id="inputResult"></span>                  </div>                  <buKon  onclick="closePopup()">  c  l  o  s  e  </buKon>          </div>  </div>

HTML

Page 42: Knocked out in knockout js

HTML

JavaScriptでDOM取得するための

id、class指定が必要

Page 43: Knocked out in knockout js

var  popup  =  document.getElementById("popup");                                                                                                        var  input  =          document.getElementById("inputForm");                                                                                                var  inputResult  =          document.getElementById("inputResult");                                                                                funcVon  openPopup(){                                                                                                                                                                inputResult.innerHTML  =  input.value;                                                                                                                          popup.style.display="block";                                                                                                                                  }                                                                                                                                                                                                funcVon  closePopup(){                                                                                                                                                              popup.style.display="none";                                                                                                                                    }  

JavaScript

Page 44: Knocked out in knockout js

JavaScript

・DOM  elementの取得

・styleの変更

・innerHTMLで変更

Page 45: Knocked out in knockout js

(´・ω・`)うーん…

Page 46: Knocked out in knockout js

 

Knockout.js  

使

Page 47: Knocked out in knockout js

knockout.jsを使った場合

Page 48: Knocked out in knockout js

funcVon  AppViewModel(){          this.popupVisible  =  ko.observable(false);          this.inputValue  =  ko.observable("");  }    ko.applyBindings(new  AppViewModel());

JavaScript

変数をkoの監視対象に設定

koを作動させる(第二引数なし→document全体が対象)

Page 49: Knocked out in knockout js

JavaScript

ViewModelの作成

変数の宣言&監視対象化

bindingしてkoを作動

Page 50: Knocked out in knockout js

HTML<div="main">                                                                                                                                                                                  <input  type="text"  data-­‐bind="value:  inputValue"></input>          <buKon  data-­‐bind="click:  popupVisible(true)">  o  p  e  n  </buKon>  </div>  <div  id="popup"            data-­‐bind="style:  {display:  popupVisible()  ?  'block'  :  'none'  }">            <div  style="opacity:1;">                  <font  color="#ffffff">popupWindow</font><br  />                  <div  style="color:#ffffff;">input.value  :                            <span  data-­‐bind="text:  inputValue()"></span></div>                  <buKon  data-­‐bind="click:  popupVisible(false)">  c  l  o  s  e  </buKon>          </div>  </div> 変数をSET

変数をGET

Page 51: Knocked out in knockout js

HTML

data-bind属性で関連付け(koで監視中の変数とリンク)

DOM取得用のid,  class不要

変数名()  :  getter

変数名(value)  :  setter

Page 52: Knocked out in knockout js

var  popup  =  document.getElementById("popup");                                                                                                        var  input  =          document.getElementById("inputForm");                                                                                                var  inputResult  =          document.getElementById("inputResult");                                                                                funcVon  openPopup(){                                                                                                                                                                inputResult.innerHTML  =  input.value;                                                                                                                          popup.style.display="block";                                                                                                                                  }                                                                                                                                                                                                funcVon  closePopup(){                                                                                                                                                              popup.style.display="none";                                                                                                                                    }  

Before

Page 53: Knocked out in knockout js

funcVon  AppViewModel(){          this.popupVisible  =  ko.observable(false);          this.inputValue  =  ko.observable("");  }  ko.applyBindings(new  AppViewModel());

After

Page 54: Knocked out in knockout js

圧倒的ではないか

 knockout.jsは

Page 55: Knocked out in knockout js

Page 56: Knocked out in knockout js

Ajax通信(jQueryを使用)

 適当に表示物を更新

 ↓

Page 57: Knocked out in knockout js

HTML<div  id="main">                  <buKon  data-­‐bind="click:  ajaxStart">  Ajax  Start  </buKon>                                                                      </div>                      <div  id="popup"                    data-­‐bind="style:  {display:  popupVisible  ?  'block'  :  'none'  }">                                                                <div  style="opacity:1;">                                                                                                                                                          <font  color="#ffffff">popupWindow</font><br  />                                                                                                      <div  style="color:#ffffff;">ajax  data<br  />                                                                                                                    <span  data-­‐bind="text:  ajaxData"></span></div>                                                                                              <buKon  data-­‐bind="click:  popupVisible(false)  ">close</buKon>                  </div>                                                                                                                                                                              </div>

Page 58: Knocked out in knockout js

funcVon  AppViewModel(){          var  self  =  this;          self.popupVisible  =  ko.observable(false);          self.ajaxData  =  ko.observable();          self.ajaxStart  =  funcVon(){                  $.ajax({                          url:  “tset”,                          type:  ”GET",                          success:  funcVon  (json){                                  var  jsonObj  =  ko.toJS(json);                                  self.ajaxData(jsonObj)                                  self.popupVisible(true);                          }                  })          }  }  ko.applyBindings(new  AppViewModel());

JavaScript  (一部)

Page 59: Knocked out in knockout js

 ∧_∧(  ・ω・)=つ≡つ(っ  ≡つ=つ`/  )  ババババ(ノ ̄∪

knockout.js?

ボコボコにしてやんよー

Page 60: Knocked out in knockout js

(って思うでしょう?)

Page 61: Knocked out in knockout js

あれ?動かない…

Page 62: Knocked out in knockout js

なぜだ、なぜ動かん…

Page 63: Knocked out in knockout js

 knockout.js

よくある落とし穴 

Page 64: Knocked out in knockout js

knockout.jsの落とし穴

監視中(observable)の変数

getterとsetterをよく間違える!

Page 65: Knocked out in knockout js

knockout.jsの落とし穴

監視中(observable)の変数

getterとsetterをよく間違える!

getter  → test_value()

setter  → test_value(val)

Page 66: Knocked out in knockout js

knockout.jsの落とし穴しかも

Page 67: Knocked out in knockout js

knockout.jsの落とし穴しかも

<input  type="text"  data-­‐bind="value:  inputValue"></input>  

valueへのbindはgetterの()は不要

Page 68: Knocked out in knockout js

knockout.jsの落とし穴しかも

<input  type="text"  data-­‐bind="value:  inputValue"></input>  

valueへのbindはgetterの()は不要

data-­‐bind=“style:  {display:  popupVisible()  ?  ‘block’  :  ‘none’  }  "  

でもこいつ↑には()必要

Page 69: Knocked out in knockout js

knockout.jsの落とし穴しかも

<input  type="text"  data-­‐bind="value:  inputValue"></input>  

valueへのbindはgetterの()は不要

(#  ゚Д゚) <  紛らわしいんじゃーい!

data-­‐bind=“style:  {display:  popupVisible()  ?  ‘block’  :  ‘none’  }  "  

でもこいつ↑には()必要

Page 70: Knocked out in knockout js

事態は見えてきた、後は簡単だ

Page 71: Knocked out in knockout js

あれ?また動かない…

Page 72: Knocked out in knockout js

なぜだ、なぜ(ry

Page 73: Knocked out in knockout js

knockout.jsの落とし穴

同変数の監視化(ko.observable)は

2回目以降はスルーされる

Page 74: Knocked out in knockout js

knockout.jsの落とし穴

同変数の監視化(ko.observable)は

2回目以降はスルーされる

funcVon  AppViewModel(){          this.popupVisible  =  ko.observable(false);          this.popupVisible  =  ko.observable(true);  }  

2回目はスルーされるのでfalseのまま

Page 75: Knocked out in knockout js

knockout.jsの落とし穴

ko.observableは1回のみ。

変数への代入はsetterで指定!

funcVon  AppViewModel(){          this.popupVisible  =  ko.observable(false);          this.popupVisible(true);  }  

setterで変数の内容変更

Page 76: Knocked out in knockout js

事態は見えて(ry

Page 77: Knocked out in knockout js

あれ?また…

Page 78: Knocked out in knockout js

五飛教えてくれ。俺は後何回画像を張ればいい…? 俺はあと何回パプテマス様の画像を張ればいいんだ?

knockout.jsは俺に何も言ってはくれない…                                                         教えてくれ、五飛!  

Page 79: Knocked out in knockout js

knockout.jsの落とし穴ko.applyBinding(koの作動)で

要素に指定できるViewModelは一つのみ

※applyBindingの第二引数でDOM要素を指定可能※

※applyBindingの第二引数を指定しないとdocument全体が対象となる※

Page 80: Knocked out in knockout js

knockout.jsの落とし穴

ko.applyBinding(koの作動)は

指定できるViewModelは一つのみ

ko.applyBindings(new  AppTestModel1()); ko.applyBindings(new  AppTestModel2());

同要素(document全体)2つはできんのだよ

Page 81: Knocked out in knockout js

knockout.jsの落とし穴対応策

Page 82: Knocked out in knockout js

knockout.jsの落とし穴対応策

ViewModelを一つのみにする

Page 83: Knocked out in knockout js

knockout.jsの落とし穴対応策

ViewModelを一つのみにする

オブジェクトを作り、それにViewModelをつなげる

or

Page 84: Knocked out in knockout js

knockout.jsの落とし穴対応策

ViewModelを一つのみにする

オブジェクトを作り、それにViewModelをつなげる

or

orDOM指定で範囲を分ける

Page 85: Knocked out in knockout js

さすがにもうこれ以上

ひっかかることは

Page 86: Knocked out in knockout js

あっ

※お察し下さい※

Page 87: Knocked out in knockout js

knockout.jsまとめ

•  JavaScriptコード量が大幅に減る

• HTML(View)との関連づけが簡単

• 動作がすごく軽い

• 大規模になると面倒くさい面が

Page 88: Knocked out in knockout js

   funcVon  draw(){                  //draw  map                  //draw  window  //                ctx.fillRect(0,  0,  SCREEN_WIDTH,  SCREEN_HEIGHT);                  ctx.clearRect(0,  0,  SCREEN_WIDTH,  SCREEN_HEIGHT);                  var  buff  =  0;                  if(imageDrag){                          buff  =  xDis  /  400  *  Math.PI  *  (-­‐1);                  }                  for(i  =  0;  i  <  IMG_NUM;  i++){                          renderOrder[i]  =  i;                          if((flagInfo[renderOrder[i]].rad  +  buff)  <  0){                                  flagInfo[renderOrder[i]].rad  =  flagInfo[renderOrder[i]].rad  +  Math.PI  *  circleMode;                          }                          else  if((flagInfo[renderOrder[i]].rad  +  buff)  >  (Math.PI  *  circleMode)){                                  flagInfo[renderOrder[i]].rad  =  flagInfo[renderOrder[i]].rad  -­‐  Math.PI  *  circleMode;                          }                  }                  //sort  for  render                  for(i  =  0;  i  <  IMG_NUM  -­‐  1;  i++){                          for(j  =  (i  +  1);  j  <  IMG_NUM;  j++){                                  if(Math.abs(Math.PI  /  2  -­‐  (flagInfo[renderOrder[i]].rad  +  buff))  <  Math.abs(Math.PI  /  2  -­‐  (flagInfo[renderOrder[j]].rad  +  buff))){                                          var  tmp;                                          tmp  =  renderOrder[i];                                          renderOrder[i]  =  renderOrder[j];                                          renderOrder[j]  =  tmp;                                  }                          }                  }                    for(i  =  0;  i  <  IMG_NUM;  i++){                          if(                                  ((flagInfo[renderOrder[i]].rad  +  buff)  >  (Math.PI  /  12))&&                                  ((flagInfo[renderOrder[i]].rad  +  buff)  <  (Math.PI  /  12  *  11))                          )                          {                                  var  mag  =  ZOOM_MIN;                                  var  temp  =  Math.abs((flagInfo[renderOrder[i]].rad  +  buff)  -­‐  Math.PI  /  2);                                  if(temp  <  ZOOM_RANGE){                                          mag  =  mag  +(ZOOM_RANGE  -­‐    temp  /  ZOOM_RANGE)  *  ZOOM_MAX;                                  }                                  ctx.drawImage(                                          drawFlagObj[renderOrder[i]],                                          parseInt(RADIUS_SIDE  *  Math.cos(flagInfo[renderOrder[i]].rad  +  buff)  +  CENTER_X  -­‐  drawFlagObj[renderOrder[i]].width  /  2  /  2  *  mag),  

                                       parseInt(RADIUS_LENGTH  *  Math.sin(flagInfo[renderOrder[i]].rad  +  buff)  +  CENTER_Y  -­‐  drawFlagObj[renderOrder[i]].height  /  2  /  2  *  mag),                                          parseInt(drawFlagObj[renderOrder[i]].width  /  2  *  mag),                                          parseInt(drawFlagObj[renderOrder[i]].height  /  2  *  mag)                                  );                          }                  }                  centerImageNo  =  flagInfo[renderOrder[IMG_NUM  -­‐  1]].imageNo;                  if(                          (mapState  ==  NORMAL)&&                          (imageDrag  ==  false)                  )                  {                          ctx.drawImage(                                  drawArrowObj[0],                                  parseInt(50),                                  parseInt((SCREEN_HEIGHT  /  2)  -­‐  drawArrowObj[0].height  /  2  +  7),                                  parseInt(drawArrowObj[0].width  /  2),                                  parseInt(drawArrowObj[0].height  /  2)                          );                  }          }    //main  loop          funcVon  mainLoop(){                  var  drawInterval  =  setInterval(funcVon(){                          if(mapState  ==  AUTO_MOVE){                                  for(i  =  0;  i  <  IMG_NUM;  i++){                                          flagInfo[i].rad  +=  autoMoveRad;                                  }                                  autoMoveFrame++;                                  if(autoMoveFrame  >=  AUTO_MOVE_FRAME){                                          autoMoveFrame  =  0;                                          mapState  =  NORMAL;                                          //change  map  detail                                          var  temp  =  $(".flagTitle");                                          var  temp2  =  $("#VtleViewer");                                          var  element  =  temp[centerImageNo].cloneNode(true);                                          temp2.empty();                                          temp2.append(element);                                  }                          }                          draw();                  },  1000  /  FPS);          }    }).call(this);  

こんな長いコード(500行)が

Page 89: Knocked out in knockout js
Page 90: Knocked out in knockout js

funcVon  AppViewModel(){          var  self  =  this;          self.popupVisible  =  ko.observable(false);          self.viewWindow  =  ko.observable(0);          $(“#statusWIndow”).swipeRight{                  viewWindow(viewWindow()++);          }            $(“#statusWIndow”).swipeLe}{                  viewWindow(viewWindow()-­‐-­‐);          }    }  ko.applyBindings(new  AppViewModel());

こうなる!(イメージ)

Page 91: Knocked out in knockout js
Page 92: Knocked out in knockout js

そう、knockout.jsならね

Page 93: Knocked out in knockout js

                                 ,.へ   ___                              ム  i     「 ヒ_i〉                            ゝ 〈     ト ノ                           iニ(()     i   {               ____            |   ヽ  i  i           /__,  ,  -­‐-­‐\           i    }     |   i         /(●)    (  ●  )        \       {、  λ     ト-┤.      /    (__人__)  \    ,ノ  ̄ ,!     i   ゝ、_      |     ´ ̄`        | ,.  '´ハ   ,!    . ヽ、    `` 、,__\              /" \  ヽ/    \ノ ノ   ハ ̄r/:::r―-­‐-­‐―/::7   ノ    /        ヽ.      ヽ::〈; .  '::.  :'  |::/   /   ,.  "            `ー 、    \ヽ::.  ;:::|/     r'"         / ̄二二二二二二二二二二二二二二二二ヽ      |  答 |     k  n  o  c  k  o  u  t  .  j  s        │|         \_二二二二二二二二二二二二二二二二ノ

もうこれで使えるはず!

Page 94: Knocked out in knockout js

別にアレをknockoutしても構わんだろう

Page 95: Knocked out in knockout js

もう何も怖くないし

Page 96: Knocked out in knockout js

   /     /     /      /  /   /  /  /     /     /     /     /    /               ビュー   ,.、  ,.、    /   /      /    /       ∠二二、ヽ    / /    /    /   /   (( ´・ω・`))             /        /                / ~~  :~~~〈   /         /    / ノ   : _,,..ゝ   /      /    /     (,,..,)二i_,∠   /    /

ちょっと川の様子を見てくるよ!

Page 97: Knocked out in knockout js

fin.

Page 98: Knocked out in knockout js

次回に続く!