42
2014/07/27 @jsCafe21 サーバサイドで動的にhtml生成していたり jQueryをガッツし使っている 既存プロジェクトにAngularJSを 部分的につっこんでみた

サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

  • Upload
    -

  • View
    663

  • Download
    0

Embed Size (px)

DESCRIPTION

サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jsCafe21

Citation preview

Page 1: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

2014/07/27 @jsCafe21

サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた

Page 2: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

名前:佐藤俊輔

twitter : @ushisantoasobu

所属 : 株式会社ジークレスト

経歴 : 主にフロントエンドエンジニア

担当 : 現在はポケットランド(スマホweb)というアバターサービス

自己紹介

Page 3: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

その前の発表がVue.jsで、そこでおそらくAngularがディスられるので省略

Angularとは

Page 4: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

「AngularってSPAつくるためのものでしょ?」

自分の勝手な思い込み

Page 5: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- Rebuild 27- mozaic.fm #3 (こちらはAngularのみを70分くらい)

「ハイブリッド」もありのようだ

Page 6: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- step1 : データバインディングで効率化- step2 : 共通モジュールをディレクティブ化- step3 : 中規模程度の新機能をSPAっぽく

担当プロジェクトでのAngular導入ステップ

Page 7: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- step1 : データバインディングで効率化 ✓

- step2 : 共通モジュールをディレクティブ化 ✓

- step3 : 中規模程度の新機能をSPAっぽく

担当プロジェクトでのAngular導入ステップ

Page 8: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

データバインディング

<p>{{message}}</p>

$scope.message = “hoge”;

.html

.js

Page 9: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

使っているところ = xhrで表示更新するところ(初期表示のhtmlについてはJavaのvelocityで生成している)

Page 10: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
Page 11: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
Page 12: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- ゲームのポイントやランキング- アイテム所持数- 報酬アイテムなどなど...結構ある

Page 13: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- 同じデータを表示する箇所が複数あっても安心- データのオブジェクトさえつっこめばいいので楽

(もうjQueryではやりたくない)

特にいいと思ったところ

Page 14: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

同じデータを複数のDOMで表示することが多々ある

Page 15: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

<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

<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

{" "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

{" "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

<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

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

負の遺産もつくってしまった、、、恥ずかしいけど書く

Page 22: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
Page 23: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

ページ表示時にサーバサイドで動的に値を埋め込んでいる、でもその後xhrでも値を更新したい、といった箇所

Page 24: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

<!-- 初期表示にvelocityで値を埋め込みたい -->

<p>$!{rank}</p>

<!-- でもangularでも書きたい(どんどん更新していくので) -->

<p>{{rank}}</p>

.html

.js

$scope.rank = 0;

どうする?

Page 25: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

<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

- 簡単にいえば「カスタムタグ」or「カスタム属性」

ディレクティブ

Page 27: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
Page 28: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
Page 29: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

サービス内の複数のページで共通で使用している機能をディレクティブ化する

Page 30: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

ディレクティブ化する前

イベント毎にソースをコピペして、値の一部を変えることで対応していた(惰性)

<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

ディレクティブ化する

.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

ディレクティブ化した後

<df furnitureid=”100522” category=”deco” posX=”0” posY=”0” scale=”0.55”></df>

.html

以後これだけでOK(でもやっぱ黒魔術的な匂いがする)

Page 33: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- ディレクティブの使いどころについては @konpyuさんのスライドがわかりやすかった http://www.slideshare.net/KonYuichi/0601-angular-note

- mozaic.fm #3 でもゲストでお話されています!

Page 34: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- 中規模程度の機能をSPAっぽくつくりたい

SPAっぽくつくりたい

Page 35: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21
Page 36: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

イベントページのタブボタン押下時の画面の切り替えを今はページ読み込みになっているけどAPIだけ返してもらっての表示の切り替えにしたい

Page 37: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- アプリっぽい挙動にしたい = サクサク感

やりたいこと

Page 38: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- フロントまわりでの処理が多くなるので 機種やOSによっては逆に描画が遅くなるかも?- htmlをキャッシュさせることでSPAを実現するけど htmlの更新の仕組みをうまくつくらないと- 既存のワークフロー(webコーダー、サーバサイド) から見直さないといけない

懸念事項

Page 39: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- jQueryも使える(angular.element)- 動的に表示を更新してく箇所がたくさんあるときは jQueryではもう書けない、 でも必ずしもAngularでなくてもよい?

まとめや補足

Page 40: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- 改めて振り返ると、、初期学習コストは高いかも- html自体がテンプレートになっているので webコーダーもみやすい- でも急に見知らぬカスタムタグつくるとビックリ されて迷惑がられる

まとめや補足

Page 41: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

- Angularっぽくないこのスライドの色合いは、 当初はW杯直前に発表する予定だったため ブラジルカラーっぽくしてるだけ

まとめや補足

Page 42: サーバサイドで動的にhtml生成していたりjQueryをガッツし使っている既存プロジェクトにAngularJSを部分的につっこんでみた @jscafe21

ご清聴ありがとうございます!