Vueカスタムイベントの紹介
Vueは要素のイベントをリッスンし、そのようなイベントが発生したときに特定の関数を実行するようにトリガーできることを私たちは知っています。 Vue.jsでは、カスタムイベントをリッスンすることもできます。これは、親コンポーネントがリッスンできるイベントを子コンポーネントが起動できるようにするための最も重要なユースケースを持つ機能です。
Vueテンプレート構文の記事で簡単なフォトギャラリーコンポーネントを作成しました。 サムネイルの行にある写真のいずれかをクリックすると、クリックした写真が下に大きなサイズで表示されます。 では、ページ全体の背景を、表示されている写真の平均的な色に設定したい場合はどうでしょうか。 これはシアターモードのように呼ぶことができます。
カスタムイベントの力は、それをかなり簡単に実行できることです。 フォトギャラリーの親コンポーネントであるApp.vue
は、写真がクリックされたときに、子コンポーネントであるPhotoGallery.vue
から写真の平均RGB値を受け取る必要があります。
始めましょう。 このチュートリアルでは、テンプレート構文チュートリアルが中断したところを取り上げます。
アプリのセットアップ
この前の投稿と同じセットアップを使用してみましょう。
カスタムイベントコードを書いてみましょう
fast-average-colorというnpm
ライブラリを使用して、特定の写真の平均カラー値を取得します。 PhotoGallery.vue
の<script>
セクションの上部にインポートします。
import from 'fast-average-color';
現在、PhotoGallery.vue
コンポーネントには、highlight()
というメソッドがあり、写真の1つをクリックするとトリガーされます。
highlight() {
event.target.id = "theater";
this.theatrical = event.target.src;
let eventIterator = event.target.parentNode;
while (eventIterator.previousElementSibling != null) {
eventIterator.previousElementSibling.getElementsByTagName('img')[0].id = "";
eventIterator = eventIterator.previousElementSibling;
}
eventIterator = event.target.parentNode;
while (eventIterator.nextElementSibling != null) {
eventIterator.nextElementSibling.getElementsByTagName('img')[0].id = "";
eventIterator = eventIterator.nextElementSibling;
}
}
この方法では、クリックした写真がサムネイルの下に大きなサイズで表示されます。 メソッド全体でevent.target
を使用したことに注意してください。 event.target
はクリックされた要素です。 これは、平均色を取得したい画像です。
fast-average-color
のドキュメントをよく読むと、getColorAsync
関数が見つかります。この関数は、color.rgba
が平均RGB値であるカラーオブジェクトを返します。 先に進んで、その関数呼び出しを行いましょう。
const fac = new FastAverageColor();
fac.getColorAsync(event.target)
.then(function(color) {
})
.catch(function(e) {
console.log(e);
});
color
ではまだ何もしていません。 最終的には、App.vue
で背景色をcolor.rgba
に設定する必要があります。 App.vue
には、color.rgba
を引数として取るメソッドがあります。 先に進んでそのメソッドを書いてみませんか?
methods: {
setBackground(rgba) {
document.querySelector('body').style.backgroundColor = rgba;
}
}
それはあなたに似合うはずです!
App.vue
のテンプレートセクションをご覧ください。 現在の外観は次のとおりです。
<template>
<div id="app">
<PhotoGallery />
</div>
</template>
App
コンポーネントは、カスタムイベントであるPhotoGallery
コンポーネントからイベントを取得する必要があります。 イベントがtheater-mode
と呼ばれたとしましょう。 コンポーネントでこのようなイベントをリッスンする場合、構文は通常のイベントの場合と同じです。 つまり、v-on:theater-mode
になります。 theater-mode
が発生すると、setBackground
メソッドが呼び出されます。
次に、値color.rgba
をApp.vue
に送信する必要があります。 PhotoGallery.vue
に戻ります。
すべてのVueコンポーネントにはメソッド$emit
があります。 このメソッドを使用すると、イベント(この場合はtheater-mode
)をトリガーできます。 カラーライブラリに対して行った非同期呼び出しから、then
関数内でthis.$emit
を呼び出します。 あなたの記憶をジョギングしましょう。
highlight() {
event.target.id = "theater";
this.theatrical = event.target.src;
let eventIterator = event.target.parentNode;
while (eventIterator.previousElementSibling != null) {
eventIterator.previousElementSibling.getElementsByTagName('img')[0].id = "";
eventIterator = eventIterator.previousElementSibling;
}
eventIterator = event.target.parentNode;
while (eventIterator.nextElementSibling != null) {
eventIterator.nextElementSibling.getElementsByTagName('img')[0].id = "";
eventIterator = eventIterator.nextElementSibling;
}
const fac = new FastAverageColor();
fac.getColorAsync(event.target)
.then(function(color) {
})
.catch(function(e) {
console.log(e);
});
}
this.$emit
は、最初の引数としてイベント名を取り、データを渡すことができるオプションの追加の引数があります。 color.rgba
を渡します。 したがって、関数呼び出しはthis.$emit('theater-mode', color.rgba)
のようになります。 新しい関数は次のとおりです。
highlight() {
event.target.id = "theater";
this.theatrical = event.target.src;
let eventIterator = event.target.parentNode;
while (eventIterator.previousElementSibling != null) {
eventIterator.previousElementSibling.getElementsByTagName('img')[0].id = "";
eventIterator = eventIterator.previousElementSibling;
}
eventIterator = event.target.parentNode;
while (eventIterator.nextElementSibling != null) {
eventIterator.nextElementSibling.getElementsByTagName('img')[0].id = "";
eventIterator = eventIterator.nextElementSibling;
}
const fac = new FastAverageColor();
fac.getColorAsync(event.target)
.then((color) => this.$emit('theater-mode', color.rgba))
.catch(function(e) {
console.log(e);
});
}
それはあなたに似合うはずです! App.vue
を振り返ってみましょう。
<template>
<div id="app">
<PhotoGallery/>
</div>
</template>
<script>
import PhotoGallery from './components/PhotoGallery.vue'
export default {
name: 'App',
components: {
PhotoGallery
},
methods: {
setBackground(rgba) {
document.querySelector('body').style.backgroundColor = rgba;
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
theater-mode
イベントを聞くことはv-on:theater-mode
のように見えることはすでに説明しました。 カスタムイベントをリッスンすると、$event
を介して渡されたすべてのデータにアクセスできます。
したがって、次のように記述します。
<template>
<div id="app">
<PhotoGallery v-on:theater-mode="setBackground($event)"/>
</div>
</template>
おめでとう!
カスタムイベントを正常に発行し、親コンポーネントからそれをリッスンし、イベントから発行された値にアクセスしました。 ブラウザを確認してください。 アプリは意図したとおりに機能するはずです。 お疲れ様でした! 🚢
Vueでのコンポーネント通信に関する知識を深めたい場合は、この記事を読んでください。