1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【初心者向け】jQueryでよく書くアレ、Vue.jsだとこう書く

1
Posted at

はじめに

長年jQueryでフロントを書いてきて、そろそろVue.jsに手を出したい――という方向けの記事です。

jQueryは今でも立派に動きますし、決して悪いライブラリではありません。ただ、画面が複雑になってくると「どのボタンを押したらどのDOMが書き換わるんだっけ?」という追いかけっこが辛くなってきます。Vue.jsに乗り換えると、この辛さがかなり楽になります。

この記事の核になる考え方は一つだけです。

jQueryは「DOMを直接いじる」、Vue.jsは「データを変えればDOMが勝手に変わる」

jQueryでは「ボタンが押されたらこの要素をshow()して、テキストを書き換えて、クラスを付けて……」とDOM操作の手順を書きます。Vue.jsでは「このデータがtrueなら表示される」「このデータがテキストとして表示される」と宣言しておいて、あとはデータを書き換えるだけ。DOMはVue.jsが勝手に面倒を見てくれます。

この頭の切り替えさえできれば、あとは書き方を覚えるだけです。本記事では、jQueryでよく書くパターンをVue.jsに書き換えながら、その切り替えを体感していきます。

準備:最小構成でVue.jsを動かす

ビルドツールもnpmも不要、<script>タグ1行から始められます。

<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
  <div id="app">
    {{ message }}
  </div>

  <script>
    const { createApp, ref } = Vue;

    createApp({
      setup() {
        const message = ref('こんにちは Vue.js');
        return { message };
      }
    }).mount('#app');
  </script>
</body>
</html>

これだけで動きます。以降のサンプルも全てこの形のsetup()内にrefを置いていく前提で書きます。

本編:書き換え対比集

1. 要素の表示・非表示

jQuery

$('#box').show();
$('#box').hide();

Vue.js

<div v-if="isVisible">表示される箱</div>
<!-- または -->
<div v-show="isVisible">表示される箱</div>
const isVisible = ref(true);
// 消したいとき
isVisible.value = false;

v-ifは要素自体をDOMから消し、v-showdisplay:noneにします。頻繁に切り替えるならv-show、条件でそもそも描画したくないならv-if

2. クリックイベント

jQuery

$('.btn').on('click', function() {
  alert('クリックされた');
});

Vue.js

<button @click="handleClick">ボタン</button>
const handleClick = () => {
  alert('クリックされた');
};

@clickv-on:clickの省略形です。HTMLを見ただけで「このボタンは何をするか」が分かるのがポイント。jQueryだと別ファイルのJSを追いかける必要がありましたよね。

3. テキストの書き換え

jQuery

$('#msg').text('更新されたメッセージ');

Vue.js

<p id="msg">{{ message }}</p>
const message = ref('初期メッセージ');
// 書き換え
message.value = '更新されたメッセージ';

{{ }}(マスタッシュ構文)に変数を入れておくだけ。変数を書き換えれば画面も自動で変わります。.text()を呼ぶ必要はありません。

4. フォーム入力値の取得

jQuery

const name = $('#name').val();
// 逆にセットしたいとき
$('#name').val('太郎');

Vue.js

<input v-model="name">
<p>入力値: {{ name }}</p>
const name = ref('');

これが双方向バインディングv-modelを付けるだけで、inputの値とname変数が常に同期します。「値を取る」「値をセットする」という発想がそもそも消えます。初めて見るとちょっと感動します。

5. クラスの付け外し

jQuery

$('#tab').addClass('active');
$('#tab').removeClass('active');
$('#tab').toggleClass('active');

Vue.js

<div :class="{ active: isActive }">タブ</div>
const isActive = ref(false);
// トグル
isActive.value = !isActive.value;

:class{ クラス名: 真偽値 }の形で渡せばOK。複数クラスも同じノリで書けます。

<div :class="{ active: isActive, disabled: isDisabled }">

6. リストの動的生成

jQuery

const items = ['りんご', 'みかん', 'ぶどう'];
$.each(items, function(i, item) {
  $('#list').append('<li>' + item + '</li>');
});

Vue.js

<ul>
  <li v-for="item in items" :key="item">{{ item }}</li>
</ul>
const items = ref(['りんご', 'みかん', 'ぶどう']);

配列に追加すれば、画面のliも勝手に増えます。

items.value.push('なし'); // 自動で<li>なし</li>が追加される

:keyはVue.jsが要素を区別するための目印です。本来は重複しないIDを指定するのがベスト。

7. Ajax通信と結果表示

jQuery

$.ajax({
  url: '/api/users',
  success: function(data) {
    $('#user-list').empty();
    $.each(data, function(i, user) {
      $('#user-list').append('<li>' + user.name + '</li>');
    });
  }
});

Vue.js

<ul>
  <li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
const users = ref([]);

const loadUsers = async () => {
  const res = await fetch('/api/users');
  users.value = await res.json();
};

loadUsers();

取得したデータをusers.valueに代入するだけで終わり。empty()してからappend()でループする、あの手順が丸ごと消えます。

8. 条件による要素切り替え

jQuery

if (isLoggedIn) {
  $('#user-menu').show();
  $('#login-btn').hide();
} else {
  $('#user-menu').hide();
  $('#login-btn').show();
}

Vue.js

<div v-if="isLoggedIn">ようこそ、{{ userName }}さん</div>
<button v-else>ログイン</button>
const isLoggedIn = ref(false);

v-if / v-else-if / v-elseが使えます。show/hideを交互に呼ぶコードから解放されます。

9. 親子要素間のデータ受け渡し

jQuery

<div id="card" data-user-id="123"></div>
const userId = $('#card').data('user-id');

Vue.js(コンポーネント化した場合)

<user-card :user-id="123"></user-card>
// UserCardコンポーネント側
const UserCard = {
  props: ['userId'],
  setup(props) {
    console.log(props.userId); // 123
    return {};
  },
  template: '<div>User: {{ userId }}</div>'
};

data-*属性でやり取りしていた値の受け渡しは、Vue.jsではpropsとして明示的に宣言します。どんなデータが渡ってくるかがコードを読むだけで分かります。

(なお、SFC(単一ファイルコンポーネント)で<script setup>を使う場合はconst props = defineProps(['userId'])とより簡潔に書けますが、ビルド環境が必要になります。)

10. グローバル状態の共有

jQuery

window.currentUser = { name: '太郎' };
// あるいはDOMに隠し持たせる
$('body').data('user', { name: '太郎' });

Vue.js

import { reactive } from 'vue';

export const store = reactive({
  currentUser: { name: '太郎' }
});

reactiveで作ったオブジェクトは、どこからインポートしても同じ実体を参照します。値を書き換えれば、それを使っている全画面が自動で更新されます。本格的にやるならPiniaというライブラリがおすすめです。

つまずきポイント

Vue.jsに触り始めたときに、ほぼ誰もが引っかかるポイントをまとめておきます。

1. refで宣言した変数は.valueが必要(JS側だけ)

const count = ref(0);
count.value++;           // JS側では .value でアクセスする
console.log(count.value); // 1(中身を見たいときも.value)
console.log(count);       // Refオブジェクトそのものが出力される点に注意
<p>{{ count }}</p>       <!-- テンプレート側では.value不要 -->

この非対称が最初は気持ち悪いですが、すぐ慣れます。

2. jQuery的に直接DOMを触りたくなる衝動を抑える

document.getElementById('xxx').innerText = '...'と書きたくなったら、まず「それはv-modelv-if、マスタッシュ構文で済まないか?」と考える癖をつけましょう。9割はVue.jsの機能で済みます。

3. リストの:keyを付け忘れる/indexを使う

v-forを書くと「:keyを付けろ」と警告されます。このkeyは要素を区別する目印なので、配列のindexではなく、データ固有のID(user.idなど)を使うのがベストです。

<!-- いまいち -->
<li v-for="(item, i) in items" :key="i">{{ item.name }}</li>

<!-- 推奨 -->
<li v-for="item in items" :key="item.id">{{ item.name }}</li>

indexをkeyにすると、配列の並び替えや途中挿入で描画がおかしくなることがあります。

まとめ

Vue.jsへの乗り換えで一番大事なのは、主語を「DOM」から「データ」に切り替えることだと思っています。

  • jQuery: 「この要素を、こう操作して、こうする」
  • Vue.js: 「このデータは、こう表示される。データを変えれば画面も変わる」

この切り替えができると、コードの見通しが劇的に良くなります。ボタンを押したらどこのDOMが書き換わるか、追いかける必要がなくなるからです。

いきなり全面リプレイスする必要はありません。jQueryで動いている画面の中の、特に込み入った部分だけをVue.jsに置き換えていく、という段階的な移行で十分です。CDN1行から始められるのがVue.jsの良いところです。

jQueryで培ったDOMやイベントの知識は全く無駄になりません。むしろ内部で何が起きているかイメージできる分、Vue.jsの挙動もすんなり理解できるはずです。

それでは、良いVue.jsライフを。

1
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?