Vue.jsで困った時に見るTips
どうも、Vue.js愛好家です。
jQuery, Knockout, Ember, Angular, React, Riotあたりは軽く触ってきた僕が、Vueに行き着いたのは神が与え給うた運命なわけですが、今回はそんなVueでちょっと複雑なことをしようとした時に見ると助かるTipsをご紹介します。
1. computedをアロー関数で記述
めちゃくちゃ使うcomputed
ですが、一般的には以下のような記法です。(あえて冗長な例を書きます
computed: {
userId() { // 三行も書かなくてはいけない
return this.user.id
},
userName() {
return this.user.name
},
userImage() {
return this.user.image
},
...
}
これ、コンポーネントによってはめちゃくちゃ多くて、行数が増えちゃいます。
実は、こうも書けます。
computed: {
userId: vm => vm.user.id, // 一行で済む!
userName: vm => vm.user.name,
userImage: vm => vm.user.image,
...
}
はい、スッキリしましたね。アロー関数の引数にはVMコンテキスト(this
)が渡るので、こういう風に書けます。
更に応用すると、こんなこともできます。
computed: {
userPath: ({$route, user}) => `${$route.path}/${user.id}`
...
}
this
の中身を展開できるので、呼び出しの階層を一段階下げられます。ちなみに、Nuxt.jsでは動きません(笑)
2. refコンポーネントのイベントをtemplate内で呼び出す
Modalコンポーネントを呼び出せるようなページを、以下のように作ります。
<template>
<div id="home">
<h1>Home Page</h1>
<button @click="$refs.modal.open">モーダルを開く</button>
<modal ref="modal"/> <!-- 自分で作ってネ -->
</div>
</template>
これはエラーが出ます。$refs.modal
が解決できるのはmounted
後なので、それ以前では$refs.modal.open
を解決できないためです。
そのため、通常はmethods
にopenModal
関数を書いて、それを@click
で呼び出すことが多いです。
@click="openModal"
...
methods: {
openModal() {
this.$refs.modal.open()
}
}
しかし、@click.stop
を使用すると、メソッドを経由せずに書くことができます。
<template>
<div id="home">
<h1>Home Page</h1>
<!-- stopを付けるだけ -->
<button @click.stop="$refs.modal.open">モーダルを開く</button>
<modal ref="modal"/>
</div>
</template>
まさにハック!笑
3. ネストしたプロパティをwatch
文字列でおk
watch: {
'$route.params.userId'(newId, oldId) {
ここに処理を書く
...
},
// メソッドも呼び出せる
'$route.query.page': 'onChangePage'
}
4. グローバルイベントの登録
全コンポーネントに共通したイベントを登録したい場合、大きく2つの方法があります。
store#actionsで登録
これが一番簡単です。this.$store.dispatch('action', params)
で呼び出せるようにする方法です。(ref. アクション)
ただ、これは$store.state
をいじるとき以外はあまり使いたくありません。
eventbusで登録
これはグローバルイベントを登録する用のモデルを用意して、そいつを経由してイベントを発火する方法です。(ref. Creating a Global Event Bus with Vue.js)
まず、プロジェクトルートに以下を作成します。
import Vue from 'vue'
export const EventBus = new Vue()
そして、グローバルイベントを登録するタイミングは、以下のようにcreated
内に$on
を用いて記述します。
<template>
<div id="home">
<h1>Home Page</h1>
<button @click="openModal('Hello Modal!')">モーダルを開く</button>
<modal ref="modal" @close="closeModal"/>
</div>
</template>
<script>
import EventBus from '@/eventbus.js
export default {
created() {
EventBus.$on('open-global-modal', this.openModal)
EventBus.$on('close-global-modal', this.closeModal)
},
// コンポーネントのdestroyedのタイミングで登録を解除したい場合は、このように書く
destroyed() {
EventBus.$off('open-global-modal', this.openModal)
EventBus.$off('close-global-modal', this.closeModal)
},
methods: {
openModal(message) {
this.$refs.modal.open(message)
},
closeModal() {
this.$refs.modal.close()
}
}
}
</script>
あとは、他のコンポーネントから同じくEventBus
経由で$emit
を呼ぶだけです。
<template>
<div id="other">
<h1>Other Page</h1>
<button @click="openModal('Hello Modal!')">モーダルを開く</button>
</div>
</template>
<script>
import EventBus from '@/eventbus.js
export default {
methods: {
openModal(message) {
EventBus.$emit('open-global-modal', message)
}
}
}
</script>
イベントの登録管理が面倒ですが、便利な場面が多々あるので、覚えていて損はないです。
5. 【非推奨】setTimeoutでレンダリングハック
もうなんだか構造が複雑過ぎて、レンダリング周りで思った挙動にならない!表示されない!だけどバグ報告が上がって、とりあえず直さなきゃ!
そんな時は、
setTimeout(() => {
...ここに処理を書く
}, 0)
Vueのライフサイクルを全無視した処理なので、全くおすすめしないですが、これで、なんとかなることは多いです(笑)。が、本当に緊急対応などでのみ使いましょう。
おわりに
僕が実装していてそこそこ使っているものを紹介しましたが、いかがでしょうか?他にも面白いTipsがあれば教えてください!