Advertisement

初めてのvue.js(2.x系)

Sep. 28, 2020
Advertisement

More Related Content

Similar to 初めてのvue.js(2.x系)(20)

Advertisement

Recently uploaded(20)

Advertisement

初めてのvue.js(2.x系)

  1. 初めてのVue.js(Vue.js 2.x 系)
 @フロントエンドカンファレンス福岡2019

  2. 自己紹介
 - 井関 健人
 - フリーランスのサーバーサイドエンジニア
 - 技術系講師してるということで駆り出される
 - 渋田 達也
 - フリーランスのフロントが得意な、なんでもエンジニア
 - 前実行委員長ということで駆り出される

  3. 本資料について
 - 本資料を用いた営利活動はご遠慮ください

  4. 本日のスケジュール
 - Vue.js って なーに?
 - Vue.js で商品一覧っぽのを作ってみる

  5. 進め方
 - 基本的には解説しながら手を動かしてもらいます
 - 手を動かしてもらいたい部分スライドには
 マークを付けています
 - ソースは全部手打ちする必要はなく、基本コピペでOKです
 作業タイム

  6. 対象バージョン
 - Vue.js 2.x 系

  7. Vue.js って、なーに?

  8. Vue.js とは?
 - 読み方
 - びゅーじぇいえす
 - 公式
 - https://jp.vuejs.org/index.html
 - 作者曰く
 - WebUIを構築するための「プログレッシブフレームワーク」

  9. プログレッシブ?
 - プログレッシブ:漸進的な

  10. フレームワーク?
 - フレームワーク framework
 - ① 骨組み。骨格。枠組み。
 - ② 体制。組織。
 - つまり、
 「こういう便利な機能を用意した」から
 「こういう方針で作ってね」が整備されたライブラリ

  11. 開発の方針があるといいことあるの?
 - 保守性が向上
 - どのファイルに何を書くかが決まる
 - ルールに則ってソースを書いていれば、
 他の人が見てもどこで何をしているかが理解しやすい

  12. - 特徴(プログレッシブフレームワーク)
 - 既存のサイトにも少しずつ使い始められる
 - おすすめの利用箇所
 - Webサイト内の小規模な機能
 - 入力フォームとフォームの確認画面
 - 小規模なSPA
 - 中大規模なSPAも可能だが、しっかりとした設計が必須
 Vue.js とは?

  13. ページ遷移のたびに HTML, js を取得 
 SPA: Single Page Application
 従来のWEB
 SPA
 index.html
 list.html
 detail1.html
 /index.html
 /app.js
 /items
 /items/1
 初回のみ HTML, js を取得 
 ページ遷移は js による DOMの再構築で実現 
 描画に必要な情報は json などで都度取得 
 json
 json
 html
 html
 html
 html

  14. - Web UI を作るための
 - 既存のサイトにも、ちょっとずつ組み込める便利な機能
 - イチから全部作り直さなくてOK
 - 何かを作るための骨組みと方針
 - こういう風に作ったら良いよー
 - 本質的には「SPAフレームワーク」ではない(後述)
 つまり、Vue.jsは?

  15. 開発環境の準備
 ~ローカル開発~

  16. ローカル + ブラウザ
 作業タイム
 1. 自分のPCに任意の場所に、
 vue_workshopという名前のディレクトリを作成
 2. 作ったディレクトリをVsCodeやAtomなどのエディタで開く
 3. vue_workshopの中に ファイル index.html と index.js を作成
 - 内容は次のスライド参照

  17. index.html の内容
 作業タイム
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv=”Pragma” content=”no-cache”>
 </head>
 <body>
 <div>
 SAMPLEコード
 </div>
 <script src="./index.js"></script>
 </body>
 </html>
  18. index.js の内容
 作業タイム
 alert("JavaScript is working!!!")
  19. - ファイルを作成できたら、index.html をブラウザで開く
 - Visual Studio Codeであれば、
 ファイル名を右クリックし、「パスのコピー」でコピーできる
 ローカル + ブラウザ
 作業タイム

  20. ブラウザで index.html を確認してみる
 作業結果チェック
 - アラートが出た後、こんな感じになればOK

  21. Vue.js が提供する機能

  22. Vueの作者が考えるフロントエンドのフレームワーク要素
 引用:https://docs.google.com/presentation/d/1WnYsxRMiNEArT3xz7xXHdKeH1C-jT92VxmptghJb5Es/edit#slide=id.g5fc474681_041

  23. - Declarative Rendering(宣言的レンダリング)
 - Component System(コンポーネントシステム)
 - Client Side Routing(クライアントサイドでのルーティング)
 - Large Scale State Management(大規模状態管理)
 - Build System(ビルドシステム)
 Vueの作者が考えるフロントエンドのフレームワーク要素

  24. - Declarative Rendering(宣言的レンダリング)
 - Component System(コンポーネント システム)
 - Client Side Routing(クライアントサイドでのルーティング)
 - Large Scale State Management(大規模状態管理)
 - Build System(ビルドシステム)
 Vue.jsと周辺ライブラリの責任範囲の区分け
 周辺ライブラリ 担当 Vue.js担当
  25. - Declarative Rendering(宣言的レンダリング)
 - Component System(コンポーネント システム)
 - Client Side Routing(クライアントサイドでのルーティング)
 - Large Scale State Management(大規模状態管理)
 - Build System(ビルドシステム)
 ここからは以下の2つを説明します
 周辺ライブラリ 担当 Vue.js担当
  26. - 単純なテンプレート構文で宣言的にデータを DOM に描画する
 - 詳細はサンプルを見ながら確認
 - Vue.jsの利用には下記のファイルをHTMLに読み込む必要がある
 - https://cdn.jsdelivr.net/npm/vue/dist/vue.js
 Declarative Rendering(宣言的レンダリング)

  27. <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv=”Pragma” content=”no-cache”>
 </head>
 <body>
 <div id="app">
 {{ message }}
 </div>
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <script src="./index.js"></script>
 </body>
 </html> Declarative Rendering(宣言的レンダリング)の例
 参考元:https://jp.vuejs.org/v2/guide/index.html
  28. new Vue({
 el: "#app",
 data: {
 message: "Hello Vue!"
 }
 })
 Declarative Rendering(宣言的レンダリング)の例
 参考元:https://jp.vuejs.org/v2/guide/index.html
  29. Declarative Rendering(宣言的レンダリング)の例

  30. Component System(コンポーネント システム)
 - 宣言的レンダリングはとても便利
 - ただし画面内のいろいろな箇所で利用するとゴチャゴチャする
 - これってプログラミングの昔からの課題
 - ちゃんと責務に分けて、見通しを良くするために必要なのが
 Component System(コンポーネントシステム)

  31. Component System(コンポーネント システム)
 - ほとんどのWEBアプリケーションはコンポーネントに分解できる
 - ヘッダ、フッタ
 - グローバルナビ
 - コンテンツの一覧
 - コンテンツの詳細
 - SNSのシェア
 - などなど

  32. スタバの商品一覧をコンポーネントに分解

  33. スタバの商品一覧をコンポーネントに分解
 ナビ 絞り込みメニュー 見出し SNS 商品一覧 商品詳細
  34. Component System(コンポーネント システム)
 - すごく雑に言えば、開発者で独自のhtmlタグを定義して、
 様々なページでそれを再利用するというもの
 - コンポーネントは「自己完結した小さく再利用しやすい」形にする
 - コンポーネントを組み合わせ、アプリケーションを構築する
 - WEB標準の「WEBコンポーネント」を参考にしている

  35. コンポーネントシステムのイメージ
 <div id="app">
 <global-nav></global-nav> 
 <item-filter></item-filter> 
 <sns-button></sns-button> 
 <head-title></head-title> 
 <items></items> 
 <footer></footer> 
 </div> ナ ビ 絞り込みメニュー 見出し SNS 商品一覧 商品詳 細
  36. コンポーネントで構成されたアプリは木構造になる
 ルート グロナビ 絞り込み メイン 見出し SNS 一覧 フッタ
  37. ルート グロナビ 絞り込み メイン 見出し リンク リンク リンク SNS 一覧 詳細 詳細 詳細 フッタ リンク リンク コンポーネントは小さなコンポーネントが集まって作られる

  38. ルート グロナビ 絞り込み メイン 見出し リンク リンク リンク SNS 一覧 詳細 詳細 詳細 フッタ リンク リンク つまり小さなコンポーネントは再利用が可能

  39. コンポーネントはある程度の塊でまたコンポーネントになる
 ルート グロナビ 絞り込み メイン 見出し リンク リンク リンク SNS 一覧 詳細 詳細 詳細 フッタ リンク リンク
  40. ルート グロナビ 絞り込み メイン 見出し リンク リンク リンク SNS 一覧 詳細 詳細 詳細 フッタ リンク リンク コンポーネントで構成されたアプリは全体も1つのコンポーネントと捉えられる

  41. Vue.jsの宣言的レンダリングの基本

  42. // index.html
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv=”Pragma” content=”no-cache”>
 </head>
 <body>
 <div id="app">
 {{ message }}
 </div>
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <script src="./index.js"></script>
 </body>
 </html> Declarative Rendering(宣言的レンダリング)の例
 参考元:https://jp.vuejs.org/v2/guide/index.html 作業タイム
 - index.htmlを以下の内容で作成

  43. - index.jsを以下の内容で作成
 // index.js
 new Vue({
 el: "#app",
 data: {
 message: "Hello Vue!"
 }
 })
 Declarative Rendering(宣言的レンダリング)の例
 作業タイム
 参考元:https://jp.vuejs.org/v2/guide/index.html
  44. index.htmlを表示するとこんな感じになる
 作業結果チェック

  45. // index.js
 new Vue({
 el: "#app",
 data: {
 message: "Hello Vue!"
 }
 })
 // index.html
 <!DOCTYPE html>
 <html>
 <head>
 <meta http-equiv=”Pragma” content=”no-cache”>
 </head>
 <body>
 <div id="app">
 {{ message }}
 </div>
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <script src="./index.js"></script>
 </body>
 </html> サンプルコードの解説

  46. 解説するには先のソースでは見づらい…?

  47. 宣言的レンダリングの例の重要なところだけ抜粋
 // index.js
 new Vue({
 el: "#app",
 data: {
 message: "Hello Vue!" 
 }
 })
 
 // index.html
 <div id="app">
 {{ message }}
 </div>
  48. これからすること
 - index.js の内容を解説
 - index.html の内容を解説

  49. 先程のソースで何が起きてるのか(1)
 // index.js
 new Vue({
 el: '#app',
 data: {
 message: 'Hello Vue!' 
 }
 })
 - Vue.jsを使うための下準備
 - new Vue() は Vue.js の定番パターン
 - Vueインスタンスを作る
 = Vueのコンポーネントを作る
 = '#app' 配下がコンポーネントになる(後述)
 - Vueの定義は「vue.js」ファイルに存在

  50. - Vueインスタンスを作る時に設定をObject 型で渡せる
 - どんなオブジェクトを作りたいかを指定
 - 具体的な説明は次のスライドで
 先程のソースで何が起きてるのか(2)
 
 // index.js
 new Vue({
 el: '#app',
 data: {
 message: 'Hello Vue!' 
 }
 })

  51. - el プロパティ
 - 宣言的レンダリングが適用される要素を指定
 - HTML と Vueインスタンス を紐付ける
 - 例では「id属性がappの要素」に
 「Vueインスタンス」が紐付く
 // index.js
 new Vue({
 el: '#app',
 data: {
 message: 'Hello Vue!' 
 }
 })
 先程のソースで何が起きてるのか(3)
 

  52. 先程のソースで何が起きてるのか(4)
 - data プロパティ
 - テンプレート構文(HTML)で利用できる変数を宣言
 - 例では変数 message を宣言的レンダリングの
 過程で利用できる
 - つまり、テンプレート構文上にある message という
 記述は Hello Vue! になる
 // index.js
 new Vue({
 el: '#app',
 data: {
 message: 'Hello Vue!' 
 }
 })

  53. - id属性 が app の中で宣言的レンダリングしたい
 - テンプレートの中では
 - 変数 message は "Hello Vue !"
 - 上記内容で描画をしてください
 index.js の内容まとめ
 // index.js
 new Vue({
 el: '#app',
 data: {
 message: 'Hello Vue!' 
 }
 })

  54. これからすること
 - index.js の内容を解説
 - 画面を描画するために必要な情報を宣言
 - index.html の内容を解説

  55. - id属性 が app のタグを用意
 - index.jsの記述により、
 この中が宣言的レンダリングの対象となる
 index.html では何を書いているのか(1)
 // index.html
 <div id="app">
 {{ message }}
 </div>

  56. - {{ message }}
 - テンプレート構文
 - {{ }} で囲まれた内容が評価され
 文字列として埋め込まれる
 - 「data要素で指定した値」や「式の戻り値」
 などを指定できる
 - 例ではindex.js で宣言した、要素dataのmessageが埋め 込まれる
 index.html では何を書いているのか(2)
 // index.html
 <div id="app">
 {{ message }}
 </div>

  57. - 宣言的レンダリングの対象範囲の指定
 - index.jsと合わせて、
 <div id="app"> の中はテンプレートになる
 - index.jsで用意した変数の利用
 - message には index.jsで指定した値を埋め込む
 index.html の内容まとめ
 // index.html
 <div id="app">
 {{ message }}
 </div>

  58. - html上に描画したい内容や適用範囲を
 テンプレート構文、HTMLタグを利用し宣言
 - js上で描画に必要となる内容を宣言
 - テンプレートとして扱うHTML要素
 - テンプレート上で使う変数、関数など
 
 テンプレートとその中で利用する値(など)を宣言し、描画してもらう
 宣言的レンダリング って何なの?
 ポイント

  59. 宣言的レンダリング のうまみ
 - ビュー と 値 の 記述を明確に分離できる
 - 変数化し抽象度を上げることで、テンプレート全体の見通しが良い
 - 「表示のON/OFF」や「繰り返し」のようなロジックを宣言的に書ける
 - DOMのappend、remove地獄から抜け出せる
 ポイント

  60. - 画面の再レンダリングコストが低い
 - 仮想DOMという仕組みで、
 純粋なJavaScriptのappendChildなどよりも低コスト(らしい)
 - Reactでも仮想DOMを利用しているので、Vue.js の専売特許じゃない
 Vue.jsを利用した宣言的レンダリングのうまみ

  61. 商品一覧っぽいものを作りながら学ぶ
 Vue.jsの宣言的レンダリング

  62. - index.html と index.js を書き換えてください
 - 内容は以降のスライドに掲載
 - index.cssを作成してください
 - 場所は index.htmlと同じフォルダ
 - 内容は以降のスライドに掲載
 これから商品一覧っぽいものを作ります

  63. - かなり長いので以下のURLにある内容をコピペしてください
 - https://gist.github.com/take2webservice/1e32992c49fa7eb9988210a1ef0 cd72c
 index.html の内容
 作業タイム

  64. - Raw を押すと、index.htmlだけを表示してくれます
 [補足]index.html の内容
 作業タイム

  65. index.js の内容
 作業タイム
 // index.js
 new Vue({
 el: '#app',
 data: {
 }
 })

  66. index.css の内容
 作業タイム
 - 長いので以下のURLにある内容をコピペしてください
 - https://gist.github.com/take2webservice/fc83bab849c0e32103edeb087c4 73947
 

  67. 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  68. - 商品一覧部分の<li>タグの部分が繰り返しで見通しが
 悪いのでなんとかする
 - 追加読み込みボタンを押したら動くようにする(未実装)
 - 価格で並べ替えできるようにする(未実装)
 これからすること

  69. Vue.jsには繰り返し表示の仕組みがあるらしい

  70. 配列を用いたタグ繰り返し(1)
 - v-for を v-for ディレクティブという
 - 配列の要素数分タグを描画
 - v-for をつけたタグを複数回描画する
 - 取り出した要素はタグの中で利用できる
 <タグ v-for="取り出した値を格納する変数名 in 配列" v-bind:key="一意な値">
 ...
 </タグ>
 ポイント

  71. - v-bind:key を v-bind:key ディレクティブという
 - v-for ディレクティブを使うときは基本セットで使う
 - 配列の中の各要素を特定する一意な値を渡す必要がある
 配列を用いたタグ繰り返し(2)
 <タグ v-for="取り出した値を格納する変数名 in 配列" v-bind:key="一意な値">
 ...
 </タグ>
 ポイント

  72. - まずは思い切って、liタグを最初の1つだけにする
 まずは繰り返すタグを選ぶ
 実演のみ
 <ul class="items">
 <li class="item">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">title1</div>
 <div class="price">1000円</div>
 </li>
 </ul>

  73. - v-forディレクティブを使ってみる
 - ディレクティブの " " の中は式として評価される
 v-forディレクティブで要素を繰り返してみる
 <ul class="items">
 <li class="item" v-for="i in [1,2,3,4,5,6,7,8,9]" v-bind:key="i">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">title1</div>
 <div class="price">1000円</div>
 </li>
 </ul>
 実演のみ

  74. 編集した index.html をブラウザで開くとこんな感じ
 - タイトルがすべて title1 になっている
 実演のみ

  75. でもこのままじゃ全部の商品名が同じ‥

  76. {{ 変数 or 式 }}
 <div>
 {{ 変数 or 式 }}
 </div>
 ポイント
 - 「テンプレート構文」 と呼ばれる
 - new Vue 実行時の引数内のdataプロパティの値や、
 その他のv-for ディレクティブで取り出した変数、
 JavaScriptの式の結果などを埋め込める

  77. - v-forディレクティブで配列から取り出した値を使ってみる
 - title の後ろに、 {{ }} で i を出力してみる
 タイトルをv-forディレクティブの値を元に表示
 <ul class="items">
 <li class="item" v-for="i in [1,2,3,4,5,6,7,8,9]" v-bind:key="i">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">title{{ i }}</div>
 <div class="price">1000円</div>
 </li>
 </ul>
 実演のみ

  78. 編集した index.html をブラウザで開くとこんな感じ
 - タイトルがすべて異なるようになっている
 実演のみ

  79. いやいや、値段とかも変えたいよね…?

  80. v-for ディレクティブに dataプロパティ の値を渡せる?

  81. ならば商品情報をdataプロパティに持たせよう!

  82. - `new Vue` するときの引数の dataプロパティを書き換える
 index.js の書き換え
 作業タイム
 new Vue({
 el: '#app',
 data: {
 items: [
 {title: 'title1', price: 1000, id: 1},
 {title: 'title2', price: 1500, id: 2},
 {title: 'title3', price: 1300, id: 3},
 {title: 'title4', price: 1100, id: 4},
 {title: 'title5', price: 2000, id: 5},
 {title: 'title6', price: 1800, id: 6},
 {title: 'title7', price: 1000, id: 7},
 {title: 'title8', price: 400, id: 8},
 {title: 'title9', price: 600, id: 9}
 ]
 }
 })

  83. - まずは思い切って、liタグを最初の1つだけにする
 index.html の書き換え(1)
 作業タイム
 <ul class="items">
 <li class="item">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">title1</div>
 <div class="price">1000円</div>
 </li>
 </ul>

  84. - 今まで配列を v-for ディレクティブの中で配列を宣言していたが、
 そこを data プロパティの中にある items に置き換える
 index.html の書き換え(2)
 作業タイム
 <li class="item" v-for="item in items" v-bind:key="item.id">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">title1</div>
 <div class="price">1000円</div>
 </li>

  85. - タイトル と 価格 を itemsから取り出した変数 item を利用して表示
 - itemはオブジェクトなのでドットでtitleとpriceを指定
 index.html の書き換え(2)
 作業タイム
 <li class="item" v-for="item in items" v-bind:key="item.id">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">{{ item.title }}</div>
 <div class="price">{{ item.price }}円</div>
 </li>

  86. 編集した index.html をブラウザで開くとこんな感じ
 - タイトルと価格が JavaScriptから取得できた
 - html の内容がスッキリした
 作業結果チェック

  87. - 商品一覧部分の<li>タグの部分が繰り返しで見通しが
 悪いのでなんとかする
 - 追加読み込みボタンを押したら動くようにする(未実装)
 - 価格で並べ替えできるようにする(未実装)
 これからすること

  88. ボタンクリックしたら動く仕組みが必要だな

  89. - DOM要素にイベントを配置する際は、v-on ディレクティブを利用
 - clickの場合は、v-on:clickとなる
 - 他にもkeyup, mouseover, blur のような馴染みのイベントも有る
 - その場合、v-on:keyup や v-on:mouseoverとイベント名の
 部分を書き換える必要がある
 イベントの配置のディレクティブ
 <タグ v-on:イベント名="実行する処理" ></タグ>
 ポイント

  90. - ボタンを押したらアラートを出してみる
 - alert ではなく this.window.alert なのは変数スコープが
 通常のHTML上のJavaScriptとは異なるため
 index.html の書き換え
 作業タイム
 <div class="btn_wrap">
 <button class="more" v-on:click="this.window.alert('ボタン押した')">さらに読み込む</button>
 </div>

  91. - さらに読み込むボタンを押すとアラートが表示される
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  92. 次は追加読み込みの関数が必要だな

  93. - メソッドの宣言はVueインスタンス生成時 に渡すObjectの中にmethodsプロパティに 用意
 - methodsはelやdataと同列
 
 - メソッド内でdataプロパティの値にアクセス する場合はthis.変数名と書く
 Vue.jsでのメソッドの定義
 new Vue({
 el: '#app',
 data: {
 },
 methods: {
 関数名(){
 関数の処理
 } 
 }
 })
 ポイント

  94. ... 省略
 {title: 'title9', price: 600}
 ]
 },
 methods: {
 loadItems() {
 alert('ボタン押した in メソッド')
 }
 }
 ... 省略
 - 関数名は loadItems 、中の処理は先程のアラートを出すもの
 - methodsの中ではスコープが異なり、今度はthis.windowが不要
 index.js の書き換え
 作業タイム

  95. index.html の書き換え
 - methodsで定義した関数は、dataプロパティに定義した値と同様に
 テンプレート上で参照できる
 作業タイム
 <div class="btn_wrap">
 <button class="more" v-on:click="loadItems">さらに読み込む</button>
 </div>

  96. - 読み込むボタンを押すとアラートが表示される
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  97. methods: {
 loadItems() {
 const items = [
 {title: 'title10', price: 1000, id: 10},
 {title: 'title11', price: 1500, id: 11},
 {title: 'title12', price: 1300, id: 12},
 {title: 'title13', price: 1100, id: 13}
 ]
 this.items.push(...items)
 }
 }
 - ボタンを押したら商品が増えるように関数を書き換えます
 - dataプロパティのitemsにアクセスするには this が必要になります
 index.js の書き換え
 作業タイム

  98. - さらに読み込むボタンを押すとアイテムがどんどん追加されます
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  99. おや?itemsへの変更が画面に即時反映されるぞ?

  100. リアクティブデータバインディング
 - Vue.jsは dataプロパティへの変更を自動 検知
 
 - 変更があった場合などはwatcherという監 視人に通知が行われる
 
 - watcherへの通知がトリガーとなり、DOM の再描画が行う
 引用: https://jp.vuejs.org/v2/guide/reactivity.html ポイント

  101. 毎回ランダムなアイテム名と価格にしたいな

  102. index.js の書き換え
 methods: {
 loadItems() { 
 this.addItems(5)
 },
 createItem() { 
 return {
 id: Math.random(), 
 title: 'title' + Math.round(Math.random() * 100), 
 price: Math.round(Math.random() * 100) * 100 
 }
 },
 addItems(count) { 
 const newItems = [...Array(count)].map(() => this.createItem())
 this.items.push(...newItems) 
 },
 }
 作業タイム
 - メソッドの中でメソッドを呼ぶ場合も this が必要になる

  103. - 追加読み込み分がランダムになった
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  104. 最初に読み込む部分もランダム生成にできる??

  105. `created`フック
 - new Vue() が呼ばれたあと、
 データの変更検知の準備が終わった状態で呼び 出される処理を記述
 
 - まだテンプレートに変数などがマウントされる前 に処理が実行される
 
 - 描画する初期データの取得が実行されることが 多い
 ポイント
 new Vue({
 el: '#app',
 data: {
 },
 created(){
 データマウント前の処理
 },
 ...
 })

  106. data: {
 items: []
 },
 created () {
 this.addItems(9)
 },
 index.js の書き換え
 作業タイム
 - data プロパティ にある items を「空の配列」にしておく
 - createdフックの中で items を初期化
 - 関数の中では this をつけて data と methods の中を参照

  107. - 最初の読み込み分もランダムになった
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  108. - 商品一覧部分の<li>タグの部分が繰り返しで見通しが
 悪いのでなんとかする
 - 追加読み込みボタンを押したら動くようにする(未実装)
 - 価格で並べ替えできるようにする(未実装)
 これからすること

  109. 並べ替えなら、dataを毎回書き換える感じかな?

  110. もっといい方法があるらしい

  111. - 自動的に値の再計算してくれる機能
 - 内部で利用する値の変更を検知し
 自動で再計算してくれる
 - リアクティブ
 - 関数と似ているが、引数をとれない
 算出プロパティ
 new Vue({
 el: '#app',
 data: {
 },
 computed: {
 算出プロパティ名(){
 return 値
 } 
 }
 })
 ポイント

  112. - sortedItemsという名前で算出プロパティ定義
 - 内容は、itemsを価格の安い順に並べ替えるというもの
 data: {
 items: []
 },
 computed: {
 sortedItems(){
 return this.items.sort((a, b) => a.price - b.price)
 }
 },
 index.js の書き換え
 作業タイム

  113. - 並び順が安い順になるよう、v-for ディレクティブでは 
 items ではなく、sortedItems を使うように変更
 index.html の書き換え
 作業タイム
 <li class="item" v-for="item in sortedItems" v-bind:key="item.id">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">{{ item.title }}</div>
 <div class="price">{{ item.price }}円</div>
 </li>

  114. - 価格が安い順になった
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  115. 高い順、安い順、読み込み順で切り替えたいな

  116. フォームの値の変更を検知 → computedで並べ替え

  117. - 「入力フォームの値」と「dataプロパティの変数」の紐付けには
 input タグ や select タグ と v-model ディレクティブを利用
 - フォームの変更に対応し、v-modelで指定した値が書き換わる
 - 値の型については注意が必要
 入力フォームの値 と dataプロパティの変数 の紐付け
 <input v-model="変数名" ></input>
 
 <select v-model="変数名" ></select>
 ポイント

  118. - フォームと紐付けるための値 order を定義
 data: {
 items: [],
 order: 'normal'
 },
 index.js の書き換え
 作業タイム

  119. - v-model ディレクティブ で フォームと値 order を紐付け
 - 値の変更を目視で確認できるように テンプレート構文で
 orderの内容を表示する
 <div>
 <select class="order" name="order" v-model="order">
 <option value="normal">読み込み順</option>
 <option value="low">価格が安い順</option>
 <option value="high">価格が高い順</option>
 </select>
 {{ order }}
 </div>
 index.html の書き換え
 作業タイム

  120. - selectの切り替えに応じて、normal, low, highと表示が切り替わる
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  121. optionタグも v-for で書き換えられそう

  122. - HTMLタグの属性にコンポーネントのプロパティを埋め込む
 - v-bind:~ のことは v-bind ディレクティブ と呼ぶ
 - 固定の値であれば、普通のHTMLのように指定してOK
 HTMLタグの属性の付与
 <タグ v-bind:属性名="コンポーネントのプロパティ" ></タグ>
 
 ex. <タグ v-bind:value="dataプロパティに定義した変数 " ></タグ>
 ポイント

  123. - 並べ替え用のselectのオプションも値として定義
 v-forディレクティブで書き出すようにする
 data: {
 items: [],
 order: 'normal',
 orderOptions: [
 { text: '読み込み順', value: 'normal' },
 { text: '価格が安い順', value: 'low' },
 { text: '価格が高い順', value: 'high' }
 ]
 },
 index.js の書き換え
 作業タイム

  124. index.html の書き換え
 <div>
 <select class="order" name="order" v-model="order">
 <option v-for="option in orderOptions" v-bind:key="option.value" v-bind:value="option.value">
 {{ option.text }}
 </option>
 </select>
 {{ order }}
 </div>
 作業タイム
 - v-bind:value で optionタグ の value属性 を設定
 - v-for で取り出した値は、v-forを適用したタグ上でも利用できる

  125. - 外見上は変わらないが、
 selectの切り替えに応じて、normal, low, high と表示が切り替わる
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  126. orderの値に応じて算出プロパティで並べ替える

  127. - order を 参照し並べ替えのロジックを分岐
 - sortは破壊的メソッドなので、[...this.items]で別オブジェクトを生成
 sortedItems() {
 switch (this.order) {
 case 'low':
 return [...this.items].sort((a, b) => a.price - b.price)
 case 'high':
 return [...this.items].sort((a, b) => b.price - a.price)
 default:
 return this.items
 }
 }
 index.js の書き換え
 作業タイム

  128. - selectの変更に応じて並べ替えが行われるようになった
 - 追加読込しても並び替えした状態になる
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  129. - 宣言的レンダリングのいいところ
 - Viewの構成の見通しがいい
 - テンプレートにロジックが入りづらい
 まとめ

  130. Vue.jsでコンポーネントシステム

  131. Component System(コンポーネント システム)
 - 宣言的レンダリングはとても便利ですが、
 画面内のいろいろな箇所で利用するとゴチャゴチャする
 - 変数や関数宣言が増えすぎる
 - これってプログラミングの昔からの課題
 - ちゃんと責務に分けて、見通しを良くするために必要なのが
 Component System(コンポーネントシステム)

  132. さっきまで作った一覧っぽいページなら

  133. さっきまで作った一覧っぽいページなら
 絞り込みメニュー 商品一覧 商品詳細 追加読み込み
  134. Component System(コンポーネント システム)
 - すごく雑に言えば、開発者で独自のhtmlタグを定義して、
 様々なページでそれを再利用するというもの
 - コンポーネントは「自己完結した小さく再利用しやすい」形にする
 - コンポーネントを組み合わせ、アプリケーションを構築する
 - WEB標準の「WEBコンポーネント」を参考にしている

  135. コンポーネントシステムのイメージ
 <div id="app">
 <order-select></order-select> 
 <item-list></item-list> 
 <show-more-button></show-more-button> 
 </div> 絞り込みメニュー 商品一覧 追加読み込み
  136. 少しずつ「一覧」をコンポーネント化してみよう

  137. - コンポーネントの定義
 - 定義したコンポーネントを使う旨の宣言
 - コンポーネントをテンプレート上で使う
 コンポーネント化と利用のステップ
 

  138. - 最低限templateプロパティに描画したいhtmlの記述があればOK
 - dataプロパティは「オブジェクトを返す関数」でなければならない
 コンポーネント定義 (Object型の変数) の用意
 ポイント
 {
 template: `コンポーネントが描画するHTML(テンプレート)`,
 data(){
 return {}
 }
 }

  139. const ItemList = {
 template: `<div>{{message}}</div>`,
 data(){
 return {
 message: "ここがコンポーネント"
 }
 }
 }
 以下の内容で item_list.js を index.js と同じ階層に作る
 作業タイム

  140. - コンポーネントの定義
 - 定義したコンポーネントを使う旨の宣言
 - コンポーネントをテンプレート上で使う
 コンポーネント化と利用のステップ
 

  141. 親コンポーネントで、子コンポーネントに名前を付け、使えるようにする
 - Vueインスタンス生成時の引数にcomponentsプロパティを定義
 - componentsプロパティは Object型の値
 - プロパティ名 :「テンプレートで利用するタグ名」
 - 値 :先程作った「コンポーネント定義」
 ポイント
 components: {
 テンプレート上でのタグ名: コンポーネント定義
 },

  142. index.js を書き換える
 作業タイム
 data: {
 items: [],
 order: 'normal',
 orderOptions: [
 { text: '読み込み順', value: 'normal' },
 { text: '価格が安い順', value: 'low' },
 { text: '価格が高い順', value: 'high' }
 ]
 },
 components: {
 'item-list': ItemList
 },
 - dataプロパティの後ろに、componentsプロパティを定義
 - Object中のプロパティは item-list という名前に対して、ItemList を定義

  143. - コンポーネントの定義
 - 定義したコンポーネントを使う旨の宣言
 - コンポーネントをテンプレート上で使う
 コンポーネント化と利用のステップ

  144. </div>
 <item-list></item-list>
 <ul class="items">
 <li class="item" v-for="item in sortedItems" v-bind:key="item.id">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">{{ item.title }}</div>
 <div class="price">{{ item.price }}円</div>
 </li>
 </ul>
 index.html を書き換える(1)
 作業タイム
 - 既存の <ul> タグ の上に <item-list>というタグを用意

  145. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <script src="./item_list.js"></script>
 <script src="./index.js"></script>
 index.html を書き換える(2)
 作業タイム
 - index.js の読み込みの上に、item_list.jsの読み込みを追加

  146. - item-list コンポーネント が表示できている
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  147. ここまでの作業内容のまとめ
 - ItemList 変数にコンポーネントの定義をつくる
 - Vue インスタンスを作る時に、
 <item-list> タグを使えるように、先程の ItemList を渡す
 - index.html 上で <item-list>タグを記述
 - index.html 上で、item_list.jsを読み込む

  148. - タグ名の定義はケバブケース
 - 例)my-component-name
 - 理由)HTML の属性名は大文字小文字を区別しないから
 - タグ名は2単語以上で構成することが推奨される
 コンポーネント定義の注意点

  149. コンポーネントの内容が固定ならここまでの方法でOK

  150. でも、今のままじゃ一覧の機能としてはデグレ
 - 初回表示時に一覧が動的に描画されない
 - 追加読み込みが動かない
 - ソートが効かない

  151. これからやること
 - 初回表示時に一覧が動的に描画させる
 - 追加読み込みが動くようにする
 - ソートを有効にする

  152. 商品情報は index.js、item_list.js どっちに持つ?

  153. - コンポーネント内でのみ完結
 - コンポーネント内の data プロパティで保持
 - 初回読み込み時に生成 or ajax で読み込むだけ
 - 値が定数で変更されない
 
 - コンポーネント外から影響を受ける
 - 影響範囲が最小となる親コンポーネントのdata プロパティで保持
 - 後述の方法で親コンポーネントから値を受け取る
 コンポーネントで利用する変数の所在
 ポイント

  154. - 商品情報には以下のような制約がある
 - 追加読み込みの際に値が更新される必要がある
 - 並び替えの際に、order 変数を参照する必要がある
 - つまり
 - 商品情報 は item-list コンポーネント内で完結しない
 - よって
 - 商品情報は item_list.js ではなく index.js で管理する
 商品情報 はどこにあるべき?

  155. - 親コンポーネントから子コンポーネントに渡す値を Prop と呼ぶ
 - テンプレート上で v-bindディレクティブを利用し、
 Prop として「変数や式」を渡す
 <コンポーネント v-bind:Prop名="変数名 や 式"></コンポーネント>
 子コンポーネントへの値の渡し方
 ポイント

  156. <div>
 <select class="order" name="order" v-model="order">
 <option v-for="option in orderOptions" v-bind:value="option.value" v-bind:key="option.value">
 {{ option.text }}
 </option>
 </select>
 {{ order }}
 </div>
 <!-- ここにあった ul タグを削除 -->
 <item-list v-bind:items="sortedItems"></item-list>
 index.html を書き換える
 作業タイム
 - 既存の商品一覧の ul タグを削除する
 - item-list コンポーネントに items という名前でsotedItems を渡す

  157. - 親コンポーネントから子コンポーネントが受け取る値を Prop と呼ぶ
 - 子コンポーネントの定義ではtemplateプロパティなどと並列に、
 propsプロパティを用意する
 - 「受け取るProp名」と「受け取るPropのデータ型」のペアを与える
 親コンポーネントからの値の受け取り方
 props: {
 受け取るProp名: 受け取るPropのデータ型
 }
 ポイント

  158. ...(省略)...
 },
 data(){
 return {
 }
 },
 props: {
 items: Array
 }
 - dataプロパティは空のObjectを返させる
 - props プロパティで 「items Prop」を受け取る
 item_list.js を書き換える(1)
 作業タイム

  159. template: `
 <ul class="items">
 <li class="item" v-for="item in items" v-bind:key="item.id">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">{{ item.title }}</div>
 <div class="price">{{ item.price }}円</div>
 </li>
 </ul>
 `,
 ...(省略)...
 - templateプロパティの内容を、index.htmlのulタグに置き換える
 - v-for ディレクティブで扱う値が items になっている点に注意
 item_list.js を書き換える(2)
 作業タイム

  160. - 要素が動的にだせるようになった
 - 追加読み込みも、ソートもできるようになってる
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  161. v-bind:component-prop="items"
 
 props: {
 componenProp: String
 }
 - v-bindディレクティブ で渡す時の Prop名 は「ハイフンつなぎ」
 - propsプロパティ で受け取る時の Prop名 は「キャメルケース」
 Prop 名の注意点
 ポイント

  162. 他の要素もコンポーネント化してみよう
 絞り込みメニュー 追加読み込み
  163. これからやること
 - 追加読み込みコンポーネントを作る
 - (絞り込みメニューコンポーネントは尺の都合で省略)

  164. show_more_button.js を index.js と同じ階層に作る
 const ShowMoreButton = {
 template: `
 <div class="btn_wrap">
 <button class="more" v-on:click="onClick">さらに読み込む(c)</button>
 </div>
 `,
 methods: {
 onClick() {
 }
 }
 }
 作業タイム
 - onClick メソッドは後で実装する

  165. index.js を書き換える
 作業タイム
 - 用意した ShowMoreButton をテンプレート上で 
 <show-more-button> タグで、利用できるようにする
 data: {
 order: 'normal',
 orderOptions: [
 { text: '読み込み順', value: 'normal' },
 { text: '価格が安い順', value: 'low' },
 { text: '価格が高い順', value: 'high' }
 ]
 },
 components: {
 'items-component': ItemList,
 'show-more-button': ShowMoreButton
 }

  166. index.html を書き換える
 </div>
 <items-component ref="items" v-bind:component-order="order"></items-component>
 <show-more-button></show-more-button>
 </div>
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <script src="./item_list.js"></script>
 <script src="./show_more_button.js"></script>
 <script src="./index.js"></script>
 作業タイム
 - 既存の <div class="btn_wrap"> を <show-more-button>
 に置き換える
 - show_more_button.js を index.js の前に読み込むようにする

  167. - 無事コンポーネント化できたら、
 ラベルが「さらに読み込む(c)」となっている
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  168. コンポーネント間の指示ってどうするんだ?

  169. - メソッドなどでイベントを発行することで、
 親コンポーネントでイベントを取得することができる
 カスタムイベントの発行
 ポイント
 this.$emit(カスタムイベント名)

  170. show_more_button.js を 書き換える
 const ShowMoreButton = {
 template: `
 <div class="btn_wrap">
 <button class="more" v-on:click="onClick">さらに読み込む(c)</button>
 </div>
 `,
 methods: {
 onClick(){
 this.$emit('click')
 }
 }
 }
 作業タイム
 - onClick メソッドで click イベントを発行する

  171. - カスタムイベントを発行する子コンポーネントのタグには、
 v-onディレクティブで親コンポーネントが実行するメソッドを指定可能
 親コンポーネントでのイベントの取得
 ポイント
 <タグ v-on:カスタムイベント名="実行するメソッド名"></タグ>

  172. - click イベントを発行する show-more-button に
 v-onディレクティブでイベント発行時に実行するメソッド名を指定
 index.html を書き換える
 作業タイム
 </div>
 <items-component ref="items" v-bind:component-order="order"></items-component>
 <show-more-button v-on:click="loadItems"></show-more-button>
 </div>
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
 <script src="./item_list.js"></script>
 <script src="./show_more_button.js"></script>
 <script src="./index.js"></script>
 

  173. - さらに読み込むボタンで追加読み込みができたらOK
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  174. - コンポーネントのポイント
 - 今回はやらなかったが、
 コンポーネントをページごとに使い回せる
 
 - ただし、上手にコンポーネントを分けないと
 不要なイベントの発行などが増えて読みづらくなる
 Vue.jsのコンポーネントまとめ

  175. Vue CLI の紹介

  176. - Vue.js での開発を高速に行うためのシステム
 - 様々な既存のエコシステムを
 - 最近は Vue.js をフル活用した開発で、主に使って行われる(はず)
 - 手軽に Vue CLI の機能の一部を体験できる資料はこちら
 - https://docs.google.com/presentation/d/1TkUZ9xYM8-9qvDmEeePcRE_DO1kZuxlPzg Lr8_eceAo/edit?usp=sharing 
 Vue CLIとは?

  177. - 時間の関係でこちらに置き換えたものをおいています
 - https://github.com/take2webservice/ItemList
 - 帰宅後に今日ご自身で書いたソースコードと見比べてみてください
 一覧画面をVue CLI用に置き換えるとどうなるか

  178. - Vue.js の ミニマムな使い方を足早に行いました
 - 今回のワークショップはVue.js の 「触り」の部分になります
 - ぜひ家に帰ってからも手を動かしてみてください
 Vueワークショップまとめ

  179. 書籍の紹介(1)
 - https://www.amazon.co.jp/dp/4863542453/
 - Vue.js の 基本的な話が載っている

  180. 書籍の紹介(2)
 - https://www.amazon.co.jp/dp/B07TB87P7M
 - コンポーネントの分け方に関するいい本

  181. ひきつづき フロントエンドカンファレンスを お楽しみください おわり
  182. 尺調整用おまけ

  183. 商品がない場合にメッセージを出したい

  184. - v-if ディレクティブ をつけた、タグ自体の表示の出し分け
 - 値がfalseの場合の処理を書きたい場合、続くタグに v-elseタグをつける
 - falseの処理が不要なら省略可
 表示の出し分けをする方法
 ポイント
 <タグ v-if="真偽値を返す値">trueの場合に表示</タグ>
 <タグ v-else>falseの場合に表示</タグ>

  185. item_list.js を書き換える(1)
 作業タイム
 - itemsに商品があるかを判断する算出プロパティhasItem を用意
 props: {
 items: Array
 },
 computed: {
 hasItem() {
 return this.items.length > 0
 }
 },
 

  186. - template プロパティを書き換え、
 v-if ディレクティブとv-else ディレクティブで出し分ける
 item_list.js を書き換える(2)
 作業タイム
 template: `
 <ul class="items" v-if="hasItem">
 <li class="item" v-for="item in items" v-bind:key="item.id">
 <img src="https://dummyimage.com/200.png/09f/fff" alt="dummy">
 <div class="title">{{ item.title }}</div>
 <div class="price">{{ item.price }}円</div>
 </li>
 </ul>
 <div v-else>商品がありません</div>
 `,

  187. - crated フックでの初期処理を削除し、
 最初の表示時に商品がない状態にする
 index.js を書き換える
 作業タイム
 created () {
 },
 

  188. - 最初には「商品がありません」と表示されればOK
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  189. - 「さらに読み込む」ボタンをおして、
 「商品がありません」が消え、一覧が表示されればOK
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  190. v-if に似たディレクティブで v-show ディレクティブがある
 - v-if
 - false の場合DOM上からタグを消す
 - v-show
 - false の場合DOM上には残る
 - スタイルでdisplay:none; を付与し見た目から消す
 v-if と v-show
 ポイント

  191. 最初に一瞬表示されるテンプレート構文は嫌だな

  192. - v-cloak ディレクティブ
 - Vue インスタンスのコンパイルが終了するまでの間残存し、
 コンパイルが終わるとDOM上から消える
 - CSS と組み合わせて、Vue インスタンスのコンパイルが終わるまで
 表示を隠せる
 初期表示を隠すテクニック
 <タグ v-cloak></タグ>
 ポイント

  193. index.html を書き換える
 作業タイム
 <body>
 <div id="app">
 <div>
 <select class="order" name="order" v-model="order" v-cloak>
 <option v-for=" option in orderOptions" v-bind:key="option.value" v-bind:value="option.value">
 {{ option.text }}
 </option>
 </select>
 </div>
 - v-cloakディレクティブ を
 「テンプレート構文の表示を隠したい要素」に付与する

  194. - v-cloak 属性があるタグを表示しないスタイルを追記する
 index.css を書き換える
 作業タイム
 .order {
 font-size: 1.3em;
 }
 
 [v-cloak] {
 display: none;
 }
 

  195. - 最初に一瞬、{{ option.text }} が表示しなくなればOK
 編集した index.html をブラウザで開くとこんな感じ
 作業結果チェック

  196. ひきつづき フロントエンドカンファレンスを お楽しみください 今度こそ おわり
Advertisement