前々回のエントリではVue.jsのコンポーネントの定義、コンポーネント間の通信について学びました。今回は 組み込みコンポーネント を深掘りします。

組み込みコンポーネント** はVue.jsが標準機能として提供する事前定義されたコンポーネントのことで、アプリケーション開発に役立ちます。

以下は主なVue.jsの組み込みコンポーネントです。

  1. 要素:
    「コンポーネントの入れ物」として機能し、あらかじめ用意されたコンポーネントをインポートし、動的な切り替えを行うための要素。
  2. 要素:
    アニメーションを作成するために使用される。DOM要素が追加、削除、または変更されたときにアニメーションを適用できる。
  3. 要素:
    複数の要素をグループ化してアニメーションを適用するために使用される。リストやグリッドなどの要素の集合を簡単にアニメーション化できる。
  4. 要素:
    再利用可能なコンポーネントを作成するために使用される。親コンポーネントから子コンポーネントにコンテンツを挿入できる。
  5. 要素:
    キャッシュされたコンポーネントを管理するために使用される。同じコンポーネントが複数回描画されるのを防ぎ、パフォーマンスを向上させることができる。
  6. 要素:
    配下の要素をページ内の指定位置に移動できる。
  7. 要素:
    非同期処理の間、待ち受けメッセージを表示できる。

組み込みコンポーネント実装例

要素と要素

以下のコードは、Vue.jsの要素を要素でラップし、タブパネルを入れ替える実装をした例です。

要素を使うことにより、タブを切り替えるたびにコンポーネントが再レンダリングされるのを防いでいます。これはパフォーマンス面で有効なテクニックですが、再レンダリングされないということは 要素を使えばフォームに入力した内容を残しておくといった用途にも使えますね。

各タブは selectedTab データプロパティによって追跡され、タブをクリックすると selectedTab の値が更新されます。また、選択されたタブの名前を表示するために currentTabName プロパティを使用しています。

tabs.html

<div id="app">
<ul class="tab">
<li class="tab-item" v-for="(tab, index) in tabs" :key="index" :class="{ 'is-active': selectedTab === index }">
<a href="#" @click.prevent="selectedTab = index">
{{ tab.name }}
</a>
</li>
</ul>
<keep-alive>
<component :is="currentTab"></component>
</keep-alive>
</div>

tabs.js

import { createApp } from 'vue'
import Tab1 from '@/components/Tab1.vue'
import Tab2 from '@/components/Tab2.vue'
import Tab3 from '@/components/Tab3.vue'

const app = createApp({
data() {
return {
tabs: [
{ name: 'Tab 1', component: 'Tab1' },
{ name: 'Tab 2', component: 'Tab2' },
{ name: 'Tab 3', component: 'Tab3' }
],
selectedTab: 0
}
},
computed: {
currentTab() {
return this.tabs[this.selectedTab].component
},
currentTabName() {
return this.tabs[this.selectedTab].name
}
},
})

app.component('Tab1', Tab1)
app.component('Tab2', Tab2)
app.component('Tab3', Tab3)

app.mount('#app')

さらにアクティブなタブを視覚的に示すことはCSSに任せましょう。クラス is-active の切り替えでアクティブなタブを表します。

tabs.css

.tab-item.is-active a {
background-color: #ccc;
font-weight: bold;
}

要素

要素を使うと要素を任意の場所に移動できます。これはたとえばダイアログを出す場合に使えます。
ボタンがHTML階層の深い場所にあったとしても、その確認ダイアログは最前面に出したいわけですから、HTML階層のより浅い場所に移動させてやるとコードがすっきりしますね。
下記の例ではダイアログを body 直下に移動させています。

teleport.html

<div id="app">
<button @click="openDialog">Open Dialog</button>
<teleport to="body">
<div v-if="showDialog" class="dialog">
<div class="dialog-overlay" @click="closeDialog"></div>
<div class="dialog-content">
<h2>Dialog Title</h2>
<p>Dialog content goes here.</p>
<button @click="closeDialog">Close Dialog</button>
</div>
</div>
</teleport>
</div>
<script src="./teleport.js"></script>
<style src="./teleport.css"></style>

teleport.js

const app = Vue.createApp({
data() {
return {
showDialog: false
}
},
methods: {
openDialog() {
this.showDialog = true
},
closeDialog() {
this.showDialog = false
}
}
})

app.mount('#app')

teleport.css

.dialog-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}

.dialog {
background-color: #fff;
padding: 20px;
border-radius: 4px;
}

要素

要素を使用するとアニメーションを適用できます。たとえば、条件に応じて要素がフェードイン・フェードアウトするようなアニメーションを実装できます。

<template>
<div>
<button @click="toggleShow">Toggle Show</button>
<transition name="fade">
<!-- アニメーションを適用したい要素を配置する -->
<p v-if="show">This element will fade in and out</p>
</transition>
</div>
</template>

<script>
export default {
data() {
return {
show: false
};
},
methods: {
toggleShow() {
this.show = !this.show;
}
}
};
</script>

<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>

要素で囲まれた

要素が、v-ifディレクティブで条件付きレンダリングされます。v-ifディレクティブによって、showの値に応じて

要素が表示・非表示になります。また、 要素のname属性に”fade”を指定しており、CSSで .fade-* のクラスを指定して、フェードイン・フェードアウトのアニメーションを設定しています。

要素の実装でよく使うプロパティ

  • name : アニメーションの名前を指定する。CSSで .name-* のようなクラスを定義することで、アニメーションを実装する。
  • appear : 要素がはじめて表示されるときにもアニメーションを適用するかどうかを指定する。
  • mode : 要素の挿入・削除のタイミングを指定する。デフォルトは”in-out”で、要素が追加される前に古い要素が削除されるが、”out-in”にすると逆になる。
  • type : トランジションの種類を指定する。デフォルトは””で、自動的に適切なトランジションが選択される。
  • duration : アニメーションの長さを指定する。
  • enter-class : 要素が追加されるときに適用されるクラスを指定する。
  • enter-active-class : 要素が追加される間に適用されるクラスを指定する。
  • **enter-to-class* : 要素が追加された後に適用されるクラスを指定する。
  • leave-class : 要素が削除されるときに適用されるクラスを指定する。
  • leave-active-class : 要素が削除される間に適用されるクラスを指定する。
  • leave-to-class : 要素が削除された後に適用されるクラスを指定する。

上記を適切に組み合わせてアニメーションを作っていきます。

所感

今回は主なVue.jsの組み込みコンポーネントについて駆け足で振り返りました。
Vue.jsの設計思想は「関心の分離」の観点から機能ごとやデザインごとに適切なサイズのファイル分割を行い、コードの再利用性や保守性を高めることが重要というものですが、組み込みコンポーネントはこれを強力に助けてくれるツールということがよくわかりました。

また transition 要素による定型化されたアニメーションの動かし方などはjQueryのeasingと大差なく、とっつきやすいと感じました。

参考資料