サーバサイドで動的にhtml生成していたりjqueryをガッツし使っている既存プロジェクトにangularjsを部分的につっこんでみた...
DESCRIPTION
サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jsCafe21TRANSCRIPT
![Page 1: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/1.jpg)
2014/07/27 @jsCafe21
サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた
![Page 2: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/2.jpg)
名前:佐藤俊輔
twitter : @ushisantoasobu
所属 : 株式会社ジークレスト
経歴 : 主にフロントエンドエンジニア
担当 : 現在はポケットランド(スマホweb)というアバターサービス
自己紹介
![Page 3: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/3.jpg)
その前の発表がVue.jsで、そこでおそらくAngularがディスられるので省略
Angularとは
![Page 4: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/4.jpg)
「AngularってSPAつくるためのものでしょ?」
自分の勝手な思い込み
![Page 5: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/5.jpg)
- Rebuild 27- mozaic.fm #3 (こちらはAngularのみを70分くらい)
「ハイブリッド」もありのようだ
![Page 6: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/6.jpg)
- step1 : データバインディングで効率化- step2 : 共通モジュールをディレクティブ化- step3 : 中規模程度の新機能をSPAっぽく
担当プロジェクトでのAngular導入ステップ
![Page 7: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/7.jpg)
- step1 : データバインディングで効率化 ✓
- step2 : 共通モジュールをディレクティブ化 ✓
- step3 : 中規模程度の新機能をSPAっぽく
担当プロジェクトでのAngular導入ステップ
![Page 8: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/8.jpg)
データバインディング
<p>{{message}}</p>
$scope.message = “hoge”;
.html
.js
![Page 9: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/9.jpg)
使っているところ = xhrで表示更新するところ(初期表示のhtmlについてはJavaのvelocityで生成している)
![Page 10: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/10.jpg)
![Page 11: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/11.jpg)
![Page 12: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/12.jpg)
- ゲームのポイントやランキング- アイテム所持数- 報酬アイテムなどなど...結構ある
![Page 13: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/13.jpg)
- 同じデータを表示する箇所が複数あっても安心- データのオブジェクトさえつっこめばいいので楽
(もうjQueryではやりたくない)
特にいいと思ったところ
![Page 14: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/14.jpg)
同じデータを複数のDOMで表示することが多々ある
![Page 15: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/15.jpg)
<div class=”point_total”>×{{targetRewardPoint}}</div>
...
<div class=”point_total”>×{{targetRewardPoint}}</div>
...
<div class=”result_point_total”>×{{targetRewardPoint}}</div>
.html
![Page 16: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/16.jpg)
<div class=”point_total”>×{{targetRewardPoint}}</div>
...
<div class=”point_total”>×{{targetRewardPoint}}</div>
...
<div class=”result_point_total”>×{{targetRewardPoint}}</div>
$scope.targetRewardPoint = data.point;
.html
.js
もちろんこれだけでOK
![Page 17: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/17.jpg)
{" "bannerDataList":null," "boxLevelBonusAchieveLevel":1," "boxLevelBonusList":[]," "completeFlg":false," "completePoint":0," "countRewardDataList":null," "currentPoint":327," "currentRank":27910," "deliveryCount":0," "deliveryCountRewardDataList":null," "orderPoint":0," "pointRewardDataList":[" " {" " " "categoryName":"アクセサリ/手系"," " " "count":1," " " "dataItemFlg":false," " " "imageUrl":"shop/clothes/acceh/acceh_10824494_shop.png"," " " "itemId":10824494," " " "itemName":"ふしぎな実"," " " "itemRare":0," " " "rewardPoint":300" " }" ]," "restRewardCount":55," "resultCd":0," "token":null}
あるAPIでこのようなjsonが返ってくるとする
![Page 18: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/18.jpg)
{" "bannerDataList":null," "boxLevelBonusAchieveLevel":1," "boxLevelBonusList":[]," "completeFlg":false," "completePoint":0," "countRewardDataList":null," "currentPoint":327," "currentRank":27910," "deliveryCount":0," "deliveryCountRewardDataList":null," "orderPoint":0," "pointRewardDataList":[" " {" " " "categoryName":"アクセサリ/手系"," " " "count":1," " " "dataItemFlg":false," " " "imageUrl":"shop/clothes/acceh/acceh_10824494_shop.png"," " " "itemId":10824494," " " "itemName":"ふしぎな実"," " " "itemRare":0," " " "rewardPoint":300" " }" ]," "restRewardCount":55," "resultCd":0," "token":null}
枠部分(報酬アイテム情報)を表示したい
![Page 19: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/19.jpg)
<div>" <div>" <img src="http://img.atgames.jp/sp/update/2014/04/icon_point.png">" " <span id=”reward_span_reward_point”></span>達成
" </div>" <div><img id=”reward_img_reward_url”></div>" <div id=”reward_div_reward_itemname”></div>" <div id=”reward_div_reward_itemcount”></div></div>
var reward = data.pointRewardData[0];jQuery(“#reward_span_reward_point”).html(reward.rewardPoint);jQuery(“#reward_img_reward_url”).attr('src', reward.imageUrl);jQuery(“#reward_div_reward_itemname”).html(“<em>” + reward.categoryName +
“</em><br>” + reward.itemName);jQuery(“#reward_div_reward_itemcount”).html(“×” + reward.count);
.html
.js
これまで自分がjQueryで書いてた方法(もっとキレイに書ける?汗)
![Page 20: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/20.jpg)
AngularJSで書いた方法。ロジック側の記述が楽
<div>" <div>" " <img src="http://img.atgames.jp/sp/update/2014/04/icon_point.png">" " <span>{{pointRewardData.rewardPoint}}</span>達成
" </div>" <div><img src="http://img.atgames.jp/{{pointRewardData.imageUrl}}"></div>" <div><em>{{pointRewardData.categoryName}}</em><br>{{pointRewardData.itemName}}</div>" <div ng-show="pointRewardData.count > 1">×{{pointRewardData.count}}</div></div>
$scope.pointRewardDataList = pointRewardDataList;
.html
.js
![Page 21: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/21.jpg)
負の遺産もつくってしまった、、、恥ずかしいけど書く
![Page 22: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/22.jpg)
![Page 23: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/23.jpg)
ページ表示時にサーバサイドで動的に値を埋め込んでいる、でもその後xhrでも値を更新したい、といった箇所
![Page 24: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/24.jpg)
<!-- 初期表示にvelocityで値を埋め込みたい -->
<p>$!{rank}</p>
<!-- でもangularでも書きたい(どんどん更新していくので) -->
<p>{{rank}}</p>
.html
.js
$scope.rank = 0;
どうする?
![Page 25: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/25.jpg)
<p>{{rank}}</p> <script>var setupAngular = function(){" var _scope = angular.element(ngCtrl).scope();" _scope.$apply(function(){" " _scope.rank = $!{rank};" });};</script>
.html
.js
$scope.rank = 0; angular.element(document).ready(function() {" if(setupAngular && typeof setupAngular === "function"){" " setupAngular(); //本体htmlのグローバルメソッドにアクセス" }});
html側のスクリプトにvelocityで吐き出される値を書き出して、、、みたいなことをやってる。しかも不要にグローバル変数をつくってしまってる
![Page 26: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/26.jpg)
- 簡単にいえば「カスタムタグ」or「カスタム属性」
ディレクティブ
![Page 27: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/27.jpg)
![Page 28: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/28.jpg)
![Page 29: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/29.jpg)
サービス内の複数のページで共通で使用している機能をディレクティブ化する
![Page 30: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/30.jpg)
ディレクティブ化する前
イベント毎にソースをコピペして、値の一部を変えることで対応していた(惰性)
<canvas id=” canvas_100522”></canvas>
<script>(function(){" var self = {}, canvas, stage, exportRoot," POS_X = 0, POS_Y = 0, SCALE = 0.55; //※ここ調整する"" self.init = function() {" " canvas = document.getElementById("canvas_100522");" " df100522_images = df100522_images||{}; " " var len = df100522.properties.manifest.length;" " for(var i = 0; i < len; i++){" " " var url = df100522.properties.manifest[i].src;" " " url = window.IMAGE_DOMAIN + "/high/roomfurniture/deco/" + url;" " " df100522.properties.manifest[i].src = url;" " } " " var loader = new createjs.LoadQueue(false);" " loader.addEventListener("fileload", self.handleFileLoad);" " loader.addEventListener("complete", self.handleComplete);" " loader.loadManifest(df100522.properties.manifest);" } " self.handleFileLoad = function(evt) { "" if (evt.item.type == "image") { df100522_images[evt.item.id] = evt.result; }" } " self.handleComplete = function() { "" //ここは省略" } " window.selfytown.df100522_shop = self;}());</script>
.html
![Page 31: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/31.jpg)
ディレクティブ化する
.directive('df', function() {" return {" " restrict: 'E'," " transclude: true," " scope: {" " " furnitureid: '@'," " " category: '@'," " " posx: '@'," " " posy: '@'," " " scale: '@'" " }," " template:" " " '<canvas id="js_canvas_dynamic_furniture_{{furnitureid}}"></canvas>'," " link:function($scope, $element){ " " " var canvas," " " " len," " " " url," " " " loader," " " " exportRoot," " " " stage;" " "" " " canvas = $element[0]; " " " len = window["df" + $scope.furnitureid].properties.manifest.length;" " " for(i = 0; i < len; i++){" " " " url = window["df" + $scope.furnitureid].properties.manifest[i].src;" " " " url = window.IMAGE_DOMAIN + "/high/roomfurniture/" + $scope.category + "/" + url;" " " " window["df" + $scope.furnitureid].properties.manifest[i].src = url;" " " } " " " //CreateJSまわりの処理は省略" " }," " replace: true" };});
.js
![Page 32: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/32.jpg)
ディレクティブ化した後
<df furnitureid=”100522” category=”deco” posX=”0” posY=”0” scale=”0.55”></df>
.html
以後これだけでOK(でもやっぱ黒魔術的な匂いがする)
![Page 33: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/33.jpg)
- ディレクティブの使いどころについては @konpyuさんのスライドがわかりやすかった http://www.slideshare.net/KonYuichi/0601-angular-note
- mozaic.fm #3 でもゲストでお話されています!
![Page 34: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/34.jpg)
- 中規模程度の機能をSPAっぽくつくりたい
SPAっぽくつくりたい
![Page 35: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/35.jpg)
![Page 36: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/36.jpg)
イベントページのタブボタン押下時の画面の切り替えを今はページ読み込みになっているけどAPIだけ返してもらっての表示の切り替えにしたい
![Page 37: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/37.jpg)
- アプリっぽい挙動にしたい = サクサク感
やりたいこと
![Page 38: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/38.jpg)
- フロントまわりでの処理が多くなるので 機種やOSによっては逆に描画が遅くなるかも?- htmlをキャッシュさせることでSPAを実現するけど htmlの更新の仕組みをうまくつくらないと- 既存のワークフロー(webコーダー、サーバサイド) から見直さないといけない
懸念事項
![Page 39: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/39.jpg)
- jQueryも使える(angular.element)- 動的に表示を更新してく箇所がたくさんあるときは jQueryではもう書けない、 でも必ずしもAngularでなくてもよい?
まとめや補足
![Page 40: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/40.jpg)
- 改めて振り返ると、、初期学習コストは高いかも- html自体がテンプレートになっているので webコーダーもみやすい- でも急に見知らぬカスタムタグつくるとビックリ されて迷惑がられる
まとめや補足
![Page 41: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/41.jpg)
- Angularっぽくないこのスライドの色合いは、 当初はW杯直前に発表する予定だったため ブラジルカラーっぽくしてるだけ
まとめや補足
![Page 42: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21](https://reader033.vdocuments.pub/reader033/viewer/2022052217/559e14561a28abd7698b4579/html5/thumbnails/42.jpg)
ご清聴ありがとうございます!