slontが2018年9月2日に投稿(2018年9月2日更新)

どうも、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を解決できないためです。

そのため、通常はmethodsopenModal関数を書いて、それを@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があれば教えてください!

↑気に入ったらシェアしてね↑
プロフィール
slont

slont

元金融エンジニア。メイン言語はJava, HTML, JavaScript, Python, Kotlinあたり。SECCONやCTF、NLP、機械学習に興味あり。金融日記購読4年。巷で話題の変態紳士。美女ソムリエ始めてました。 お仕事の依頼はTwitterからお願いします。

comments powered by Disqus
スポンサーリンク
Back to top