カテゴリー
サインイン 新規登録

間違いや改善の指摘

内容の技術的な誤り・誤字脱字やミスのご報告・解説やトピックの追記/改善のご要望は教材をさらに良くしていく上でとても貴重なご意見になります。

少しでも気になった点があれば、ご遠慮なく投稿いただけると幸いです🙏

実際には誤りではなく勘違いであっても、ご報告いただけることで教材のブラッシュアップにつながります。

質問ポリシー①

教材受講者みなさんのスムーズな問題解決のために、心がけていただきたいことがあります。

教材の内容に関する質問を投稿しましょう

教材の内容に関係のない質問や教材とは異なる環境・バージョンで進めている場合のエラーなど、教材に関係しない質問は推奨していないため回答できない場合がございます。

その場合、teratailなどの外部サイトを利用して質問することをおすすめします。教材の誤字脱字や追記・改善の要望は「文章の間違いや改善点の指摘」からお願いします。

1-1

jQuery で実装を見てみよう

jQuery で実装を見てみよう

このパートでは jQuery を使った実装をしてみましょう。

本パートの目標物(ゴール)

本パートでは jQuery を使って Twitter 風フォローボタンを実装していただきます。実際にリアル DOM を操作してみて、何が問題なのかを明確にします。

完成例のコードはこちら

目標物を作成するまでの流れ

サーバーから受け取った HTML に対して jQuery を使ってリアル DOM を操作します。

  1. jQuery プロジェクトの作成
  2. index.html の作成と css の作成
  3. script.js の作成と実装

では実際に進めていきましょう。

1. jQuery プロジェクトの作成

はじめにプロジェクトを作成します。任意のディレクトリで下記の構成を作成してください。

Copied!
└── src ├── index.html ├── script.js └── style.css

2. index.html の作成と css の作成

以下の HTML ファイルは、サーバーサイド(例えば PHP など)からもらった HTML を想定しています。ではsrc/index.htmlを以下のように編集してください。

index.html

html
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
Copied!
<html lang="ja"> <head> <link rel="stylesheet" href="style.css" /> </head> <body> <main> <div id="app"> <ul class="accountList"> <li class="accountList__item js-account-item" data-follow="false" data-id="1" > <div> <div class="account__summary"> <div> <p class="account__name">リオネル・メッシ</p> <p class="account__team">FCバルセロナ</p> </div> <div> <button type="button" class="js-follow-btn followBtn"> フォローする </button> </div> </div> <p class="account__description"> アルゼンチンサンタフェ州ロサリオ出身のイタリア系アルゼンチン人サッカー選手。リーガ・エスパニョーラ・FCバルセロナ所属。アルゼンチン代表。ポジションはフォワード (wikipedia) </p> </div> </li> <li class="accountList__item js-account-item" data-follow="true" data-id="2" > <div> <div class="account__summary"> <div> <p class="account__name">クリスティアーノ・ロナウド</p> <p class="account__team">Juventus</p> </div> <div> <button type="button" class="js-follow-btn followBtn"> フォロー中 </button> </div> </div> <p class="account__description"> ポルトガル・フンシャル出身のサッカー選手。セリエA・ユヴェントスFC所属。ポルトガル代表。ポジションはフォワード (wikipedia) </p> </div> </li> <li class="accountList__item js-account-item" data-follow="false" data-id="3" > <div> <div class="account__summary"> <div> <p class="account__name">ネイマール</p> <p class="account__team">パリサンジェルマン</p> </div> <div> <button type="button" class="js-follow-btn followBtn"> フォローする </button> </div> </div> <p class="account__description"> ブラジル・サンパウロ州モジ・ダス・クルーゼス出身のサッカー選手。ブラジル代表。リーグ・アン・パリ・サンジェルマンFC所属。ポジションはフォワード (wikipedia) </p> </div> </li> </ul> </div> </main> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="script.js"></script> </body> </html>

簡単に説明

この部分で style をリンクさせています。実際の style.css は後ほど記載いたします。

html
1
Copied!
<link rel="stylesheet" href="style.css" />

今回は data-follow (data 属性)を使用して DOM から情報を受け取るようにしています。

html
123
Copied!
<li class="accountList__item js-account-item" data-follow="false" data-id="1"> // 各アカウント </li>

次に、ボタンをクリックしたら フォロー・フォロー解除解除ができるように js 用の class を指定しています。

html
123
Copied!
<button type="button" class="js-follow-btn followBtn"> フォローする </button>

次に style.css ですが、こちらは見た目だけになりますので、詳細な説明は省略させていただきます。下記コードをコピー & ペーストしていただければ大丈夫です。

css
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
Copied!
/** 共通スタイル **/ html { font-size: 62.5%; } body { background: #fafafa; font-size: 1.6rem; color: #222; } ul { list-style: none; margin: 0; padding: 0; } p { margin: 0; padding: 0; } /** アカウント一覧スタイル **/ #app { width: 100%; max-width: 640px; margin: 100px auto; padding: 0; background: #fff; border: solid 1px #e0e0e0; } .accountList { padding: 0; margin: 0; } .accountList__item { position: relative; padding: 1rem; border-bottom: solid 1px #e0e0e0; } .accountList__item:last-child { border: 0; } .account__summary { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .account__name { font-weight: 700; } .account__team { font-size: 1.2rem; color: #646464; } .account__description { font-size: 1.4rem; } .followBtn { display: inline-block; min-width: 100px; border: 0; touch-action: manipulation; cursor: pointer; padding: 0 1rem; height: 32px; line-height: 32px; font-weight: 800; outline: none; position: relative; border: solid 1px #e0e0e0; background: #fff; color: #222; border-radius: 16px; } .followBtn:hover { background: #e0e0e0; } .followBtn.isFollow { background: rgb(29, 161, 242); border: solid 1px rgb(29, 161, 242); color: #fff; } .followBtn.isFollow:hover { opacity: 0.7; }

3. script.js の作成と実装

次に script.js を実装します。以下のコードを追加してください。

javascript
1234567891011121314151617181920212223242526272829
Copied!
$(function () { $(".js-account-item").each(function () { var $this = $(this); var $thisData = $this.data(); if ($thisData.follow) { $this.find(".js-follow-btn").addClass("isFollow"); } }); $(".js-follow-btn").on("click", function () { var $this = $(this); var $accountItem = $this.parents(".js-account-item"); var $thisData = $accountItem.data(); if ($thisData.follow) { // ajax $this.removeClass("isFollow"); $this.text("フォローする"); $accountItem.data("follow", false); } else { // ajax $this.addClass("isFollow"); $this.text("フォロー中"); $accountItem.data("follow", true); } }); });

細かくみていきます。
ブラウザで表示されるたびに、下記 html の data-follow="false"でアカウント一人一人がすでにフォローしているのかどうかをチェックしています。
そして true の場合には、ボタンに対して isFollow クラスを追加しています。

html
123
Copied!
<li class="accountList__item js-account-item" data-follow="false" data-id="1"> // 各アカウント </li>
javascript
1234567
Copied!
$(".js-account-item").each(function () { var $this = $(this); var $thisData = $this.data(); if ($thisData.follow) { $this.find(".js-follow-btn").addClass("isFollow"); } });

次にボタンをクリックをした場合に フォローかフォロー解除か切り替える必要がありますね。
下記の部分でクリックをしたら、data-follow が true であれば

  • isFollow クラスを削除
  • ボタンのテキストを「フォローする」にする
  • data-follow を false に変更

ということをしています。data-follow が false の場合は全く正反対のことをしています。
さらに今回は割愛させていただいていますが、実際のプロダクトであれば ajax を使ってサーバーサイドにフォロー・フォロー解除の変更がされたことを送信しなければいけません。

javascript
12345678910111213141516171819
Copied!
$(".js-follow-btn").on("click", function () { var $this = $(this); var $accountItem = $this.parents(".js-account-item"); var $thisData = $accountItem.data(); if ($thisData.follow) { // ajax $this.removeClass("isFollow"); $this.text("フォローする"); $accountItem.data("follow", false); } else { // ajax $this.addClass("isFollow"); $this.text("フォロー中"); $accountItem.data("follow", true); } });

動作確認

ではブラウザで表示をさせてみましょう。任意のブラウザに index.html をドラッグ & ドロップをしてみましょう。
以下のように表示され、フォローボタンが作動していれば大丈夫です。

Image from Gyazo

jQuery での状態変更の流れ

おさらいとしてフォロー・フォロー解除の流れをもう一度確認しましょう。

  1. DB を元にサーバーサイドから受け取った HTML をブラウザにレンダリング
  2. レンダリングされた HTML の中から フォロー中のアカウントを探してフォロー状態の見た目にする
  3. フォローボタンがクリックさする。
  4. そのフォローボタンに紐づくアカウントの data 属性を確認してフォローする。
  5. ついでにテキストも変更する。

となっています。もう少し噛み砕いていうと見た目を基準に操作していることがわかります。jQuery でも昨今のフロントエンドフレームワークと同じことができることがわかったかと思います。ですが、その見た目(DOM)基準に操作することに問題点があります。

リアル DOM 操作の問題点

見た目を操作をもう少し専門的に言うと DOM 操作と言います。では、その DOM 操作の問題点とはなんでしょう。

  1. ロジックが UI に依存してしまっている。
  2. 状態の管理が難しい。

と言うことが挙げられます。

ロジックが UI に依存してしまっている

今回の実装を思い出してみましょう。HTML に直接記述されている data 属性を元にフォローかどうかの判定をしていました。

html
123
Copied!
<li class="accountList__item js-account-item" data-follow="false" data-id="1"> // 各アカウント </li>

HTML の作りに依存してしまっていますよね。極端な話アカウントのデータと HTML が紐付きすぎてしまっていて、ロジックと UI を分離することが難しいことが伺えます。

実際の開発でしたら、例えば既存サービスをリデザインをするときに問題が表面化しやすいです。
jQuery の場合、今回は規模も小さいですが、 一例として、以下のコードでは hoge クラスの要素の子要素である button をクリックした時の動作を追加しています。
リデザインでどうしても HTML の構造を変更しなければいけない場合どうでしょう?具体的には buttonhoge の子要素では無くなっていたら・・・
これだけでボタンが動作しなくなってしまいますよね。

javascript
12345
Copied!
$(".hoge") .children("button") .on("click", function () { // 何か処理 });
html
12345678
Copied!
<div class="hoge"> <button type="button">送信</button> </div><div class="hoge"> 下記のボタンをクリック </div> <button type="button">送信</button>

状態の管理が難しい

今回の実装ではフォローかどうかの状態しかありませんでした。なので、そんなに複雑にはなっていませんが、これがもっと大規模な WEB アプリケーションではどうでしょう。
同じように Twitter の場合でしたら、メッセージが来ていたら、通知が来ていたら新しいツィートが来たらなどの状態がありますね。そうすると jQuery、もっと突き詰めると リアル DOM での操作では状態の管理が難しくなってしまいます。おそらく人間では全体を把握することが不可能なほど・・・。

終わりに

1 章では jQuery を使い、大規模な WEB アプリケーションでの DOM 操作による状態の管理の難しさを説明しました。次の章では仮想 DOM を使ったライブラリーである React を使い同じように Twitter 風フォローボタンを実装していただきます。

お疲れさまでした!

現在のパート (1)
全パート (5)
みんなで助け合おう!
現在のパートのディスカッション 全1件
1-1
わた 2020-10-30
body タグにある属性

data-feedly-mini="yes" はどういう意味でしょうか?どんな時に使える属性でしょうか?