Vue.js

JQueryをVue3に置き換えてみよう【サンプルあり】

JQueryをvue.jsに置き換えてみよう
ニャンコ
ニャンコ

最近「jQuery 4.0」が公開されましたが、以前から「jQuery」はオワコンと言われることが多いですよね。
私は今も通常のWEBサイトを作成する際は「jQuery」を使用しているので、全然オワコンとは思っていません。

ですが、今回は会えてJQueryVue.jsに置き換えてみたいと思います。
jQueryで良く実装される処理をVue.jsを使用して実装していきます。

ワンコ
ワンコ

Vue.jsをCDNで読み込む

Vue.jsを使用する時は、プロジェクトを作成~と思ったかもしれませんが、Vu.jsはCDNで読み込むことができます。
CDNは以下の通りです。

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

ちなみにCDNでの読込に関しては、以下のマニュアルに記載されています。

またプロジェクト作成から学びたいという方は、プロジェクト作成に関しての記事がありますので、そちらをご覧ください。

関連動画

ハンバーガーメニューの実装

Vue.jsを読み込んだら、まずはスマホサイトに必須のハンバーガーメニューから作成します。
サンプルはこちら!といっても、Vue.jsで作られてるだけで普通のハンバーガーメニューです。
ハンバーガーボタンを押すと.openクラスを付与することで、変化するようにしています。

See the Pen Untitled by kokusyo (@kokusyo) on CodePen.

ソースがこちら。
ハンバーガー実装に必要な箇所だけ抜き出しています。
全ソースはサンプルから確認できます。

<!-- 「id:app」の中にVueアプリケーションを作成 -->
<div id="app">
    <header>

        <!-- ハンバーガーメニュー -->
        <!-- クリックイベントとクラスをバインド -->
        <button type="button" class="btn js-btn" @click="openMethod">
            <span class="btn-line" :class="{open:isOpen}"></span>
        </button>

        <!-- ハンバーガーメニューを押したら出るメニュー -->
        <nav>
        <ul class="menu" :class="{open:isOpen}">
            <li class="menu-list">メニュー1</li>
            <li class="menu-list">メニュー2</li>
            <li class="menu-list">メニュー3</li>
            <li class="menu-list">メニュー4</li>
            <li class="menu-list">メニュー5</li>
        </ul>
        </nav>
    </header>
</div>

<!-- CDNでVue.js読み込み -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
// VueからcreatApp関数と、ref関数をインポート
const { createApp, ref } = Vue
const app = Vue.createApp({
    setup() {

        // リアクティブ変数を作成
        const isOpen = ref(false);

        // ハンバーガーボタンを押した際のイベント
        const openMethod = () => {
            isOpen.value = !isOpen.value;
        };
        return {
            openMethod,isOpen
        };
    }
});

//「id="app"」内に表示
app.mount('#app');

ソース解説

ソースのポイントを見ていきます。

HTML

クリックイベント

まずは、htmlのハンバーガーボタンから。

<button type="button" class="btn js-btn" @click="openMethod">
    <span class="btn-line" :class="{open:isOpen}"></span>
</button>

Vue.jsでイベントを設定するには、v-onディレクティブを使用します。
v-onは省略して@で表現できます。

v-on:イベントの種類="メソッド名"

もしくは

@イベントの種類="メソッド名"

これでハンバーガーボタンをクリックした際の、イベントを設定できます。

クラスのバインド

また、「open」クラスのオンオフを切り替えている部分がこちら。
Vueでは、タグの属性に変数を使用したい場合、v-bindを使用します。
こちらも省略した書き方があり、で表すことが可能です。

<span class="btn-line" v-bind:class="{open:isOpen}"></span>

もしくは

<span class="btn-line" :class="{open:isOpen}"></span>

{ }で囲まれた部分、openがクラス名で、isOpenがVueで定義した変数です。
scriptブロックで呈したisOpenには、trueかfalseが入るようになっています。
trueの場合は、openクラスが付与されます。

// trueの場合は、openクラスが付与される
<span class="btn-line" v-bind:class="{open:true}"></span>
// falseの場合は、openクラスなし
<span class="btn-line" v-bind:class="{open:false}"></span>

Scriptブロック

続いてはVueのScriptブロック
Vueでは、システム内で使用したい関数やライブラリをインポートして使用します。
今回は、Vueアプリケーションを作成するcreateApp関数と、リアクティブな変数を作成するref関数をインポートしています。

const { createApp, ref } = Vue

createApp()は、Vueアプリケーションを作成する関数で、createApp()で作成したアプリケーションをmount()関数で画面に表示させます。

// createAppでアプリケーション作成
const app = Vue.createApp({
    
省略

});

//「id="app"」内に表示
app.mount('#app');

Vueアプリケーションを画面に表示させる処理の次は、実際の処理の中身を確認します。
createApp()の中にさらに、setup()があります。
このsetup()はVue.js 3.0から導入されたComposition APIの一部で、コンポーネント内でリアクティブなデータを管理するために必要な記述です。
ただ、本来のコンポーネントではもっと簡潔に記述できるので、この書き方はこういうものだとおまじない的に思って入ればいいと思います。

const app = Vue.createApp({

    // リアクティブなデータとメソッドを定義
    setup() {

        // リアクティブ変数を作成
        // 初期値としてfalseを設定
        const isOpen = ref(false);

        // ハンバーガーボタンを押した際のメソッド(イベント)
        // 処理の内容は、trueとfalseを切り替えるだけ
        const openMethod = () => {
            isOpen.value = !isOpen.value;
        };

        // 定義した変数とメソッドを返す
        return {
            openMethod,isOpen
        };
    }

});

そもそもコンポーネント、リアクティブ変数が分からない方は、別記事にまとめているので、こちらをご確認ください!

ワンコ
ワンコ
関連動画

タブ切り替えの実装

続いてはタブ切り替えの実装です。
今回はクラスの切り替えではなく、v-ifディレクティブで実装しました。

See the Pen Untitled by kokusyo (@kokusyo) on CodePen.

<div id="app">
  <div class="wrap">
    <ul class="tab_btn">

      <!-- v-forを使用してタブの一覧作成
      クリックイベントとアクティブ時のクラス設定 -->
      <li v-for="(tab, index) in tabs" :key="index" @click="activeMethod(index)" 
          :class="{ active: active === index }">
        {{ tab }}
      </li>
    </ul>
    
    <!-- v-if でタブのコンテンツの表示を切り替える -->
    <ul class="tab_content">
      <li v-if="active === 0">タブ1 content</li>
      <li v-else-if="active === 1">タブ2 content</li>
      <li v-else-if="active === 2">タブ3 content</li>
    </ul>
  </div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
const { createApp, ref } = Vue
const app = Vue.createApp({
    setup() {

      // タブの一覧
      const tabs = ref(['タブ1', 'タブ2', 'タブ3']);
      
     // アクティブなタブを示す変数
      const active = ref(0);

      // タブをクリックした際のイベント
      // アクティブなタブの番号を入れる
      const activeMethod = (tab) => {
        active.value = tab;
      };

      return {
        activeMethod,
        active,
        tabs
      };
    }
});

ソース解説

HTML

v-forはループのディレクティブで、ループ対象を一つづつ取り出して、タグを作成してくれます。
今回は、scriptブロックで定義したタブの一覧をループの対象にしています。
また、アクティブなタブは色が変わるよう、配列のインデックス番号とアクティブなタブの番号が同じ場合activeクラスを付与しています。

<ul class="tab_btn">
  <li v-for="(tab, index) in tabs" :key="index" @click="activeMethod(index)" 
      :class="{ active: active === index }">
    {{ tab }}
  </li>
</ul>

v-ifディレクティブは表示を切り替える条件を指定できます。
アクティブなタブと番号が同じなら表示するという条件を指定しています。

<ul class="tab_content">
  <li v-if="active === 0">タブ1 content</li>
  <li v-else-if="active === 1">タブ2 content</li>
  <li v-else-if="active === 2">タブ3 content</li>
</ul>

Scriptブロック

ハンバーガーメニューの処理と比べて特に新し要素はありません。
v-forでループさせる配列の作成と、アクティブなタブを格納する変数を定義し、初期値は1枚目のタブが表示されるように「0」を指定しています。

// タブの一覧
const tabs = ref(['タブ1', 'タブ2', 'タブ3']);
      
// アクティブなタブを示す変数
const active = ref(0);

タブをクリックした際のイベントを定義しています。
アクティブなタブを書くのする「active」にクリックされたタブの番号を格納します。
「active」変数に番号を格納するだけで、画面表示が自動で切り替わるのが「Vu.js」の便利なところです。

// タブをクリックした際のイベント
// アクティブなタブの番号を入れる
const activeMethod = (tab) => {
    active.value = tab;
};

スライドダウン/スライドアップ実装

続いて、スライドダウン/スライドアップの実装。
JQueryには専用の関数があるので楽ですが、Vueで実装するには少し処理が必要です。

See the Pen Untitled by kokusyo (@kokusyo) on CodePen.

<div id="app">
  <div class="wrap">
    <button @click="isOpen = !isOpen">Toggle</button>
    <transition name="slide-fade">
      <div v-show="isOpen" class="content">Content</div>
    </transition>
  </div>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
.content {
  padding: 10px;
  border: 1px solid #000;
  transition: 0.3s ease-out;
  transform-origin: top;
}

/* アニメーション開始前の状態 */
.slide-fade-enter-from, .slide-fade-leave-to {
  transform: scale(1,0);
  opacity: 0;
}

/* アニメーション終了状態 */
.slide-fade-enter-to, .slide-fade-leave-from {
  transform: scale(1,1);
  opacity: 1;
}
const { createApp, ref } = Vue
const app = Vue.createApp({
    setup() {

      // 開閉状態を表す変数
      const isOpen = ref(false);

      return {
        isOpen
      };
    }
});
app.mount('#app');

ソース解説

HTML/CSS

Vue には、状態の変化に応じてトランジションやアニメーションを扱うコンポーネントがあります。
それが、今回使用しているTransitionです。
Transitionは要素が DOM に enter (挿入) 、leave (削除) される時にアニメーションを適用します。

<!-- ボタンクリックで開閉を切り替え -->
<button @click="isOpen = !isOpen">Toggle</button>

<!-- transitionコンポーネントにslide-fadeという名前を付けています。
これにより付与されるクラスを指定できます。 -->
<transition name="slide-fade">
    <div v-show="isOpen" class="content">Content</div>
</transition>

name属性に付与した、「slide-fade」のスタイルを指定します。
「〇〇-enter-from」や「〇〇-leave-to」などのクラスは、Transitionコンポーネントにより自動で付与されます。

/* アニメーション開始前の状態 */
.slide-fade-enter-from,
.slide-fade-leave-to {
  transform: scale(1,0);
  opacity: 0;
}

/* アニメーション終了状態 */
.slide-fade-enter-to,
.slide-fade-leave-from {
  transform: scale(1,1);
  opacity: 1;
}

それぞれのクラスの役割は以下の通りです。

slide-fade-enter-fromアニメーションが始まる前の状態を定義します。つまり、何か(例えば、ボタンやテキストなど)が画面に表示される前の状態です。その何かが画面に表示される直前に追加され、1フレーム後に削除されます。
slide-fade-enter-toアニメーションが終わった後の状態を定義します。つまり、何かが完全に画面に表示された後の状態です。このクラスは、その何かが画面に表示されると同時に追加され、アニメーションが完了すると削除されます。
slide-fade-leave-from要素が画面から消える前の状態を定義します。このクラスは、その何かが画面から消える直前に追加され、1フレーム後に削除されます。
slide-fade-leave-to要素が画面から完全に消えた後の状態を定義します。このクラスは、その何かが画面から消えると同時に追加され、アニメーションが完了すると削除されます。

まとめ

以上 JQueryをVue3に置き換えてみようでした。

ワンコ
ワンコ

えっ わざわざVue3に置き換える必要ないと思うだって?

ワンコ
ワンコ

たしかに...

ワンコ
ワンコ

今回は単純な処理だけで、むしろJQueryの方が簡単に実装できそうな内容でしたね。

ワンコ
ワンコ

-Vue.js
-,