Vue.jsを利用した地図アプリ(後編)

Image from Gyazo

親子コンポーネントのイベント処理

地図アプリに配置した上下左右のボタンのイベント処理を実装します. このアプリは3つのコンポーネントで構成されています. 親コンポーネントは main.vue ,子コンポーネントは vmap.vuevcontroller.vue です. 親子コンポーネント間でメソッドを呼び出したり,データを受け渡すには幾つか方法がありますが, 子から親親から子 ではその方法が異なります. 今回の地図アプリでは下記の流れでイベント処理を行います.

  1. vcontroller.vue(子) のボタンをクリックすると,main.vue(親)moveメソッドを呼び出す(子から親).
  2. main.vue(親)moveメソッドが呼び出されると,vmap.vue(子)moveメソッドを呼び出す(親から子).

Image from Gyazo

子から親のメソッドを実行

子コンポーネントから親コンポーネントのメソッドを呼び出すには$emitを利用します.

main.vue(親)

親コンポーネントで moveメソッドを定義します. このmoveメソッドはアラートを表示するだけです. このメソッドを v-onディレクティブを利用して,vcontorllerタグの属性として指定します. このとき,move-eventという属性名になっていることに注意してください.

<template>
  <div>
    <h1>Vue.jsで地図アプリ</h1>
    <vmap></vmap>
    <vcontroller v-on:move-event="move"></vcontroller>
  </div>
</template>

<script>
import vmap from "./vmap"
import vcontroller from "./vcontroller"
export default{
  components:{
    vmap,
    vcontroller
  },
  methods:{
    move(direction){
      // アラートを表示
      alert(direction);
    }
  }
}
</script>

vcontroller.vue(子)

子コンポーネントでも moveメソッドを定義しています. このmoveメソッドは,$emitを利用してmove-eventとして登録されている親コンポーネントの moveメソッドを呼び出します. また,moveメソッドは,v-onディレクティブを利用して,ボタンのクリックがトリガーとなっています. このとき,メソッドの引数としてleft, up, right, downのいずれかの文字列が渡されることに注意してください.


<template>
  <div>
    <div id="mycontroller">
      <div id="mypad">
        <v-fa class="pad" v-on:click="move('left')" icon="long-arrow-alt-left" />
        <v-fa class="pad" v-on:click="move('up')" icon="long-arrow-alt-up" />
        <v-fa class="pad" v-on:click="move('right')" icon="long-arrow-alt-right" />
        <v-fa class="pad" v-on:click="move('down')" icon="long-arrow-alt-down" />
      </div>
    </div>
  </div>
</template>

<script>
// ・・・省略・・・

export default{
  name: "vcontroller",
  methods:{
    move(direction){
      // 親コンポーネントであるmain.vueのmoveメソッドを呼び出す      
      this.$emit("move-event", direction)
    }
  }
}
</script>

ボタンをクリックすると,対応した文字列がアラートに表示されます.

Image from Gyazo

親から子のメソッドを実行

親コンポーネントから子コンポーネントのメソッドを呼び出すには$refsを利用します.

vmap.vue(子)

子コンポーネントで move メソッドを定義します. このメソッドでは,引数の文字列に応じて,Leefletの地図オブジェクトの中心を東西南北の方向に少しだけ移動させます.

<script>
import L from 'leaflet'
import "leaflet/dist/leaflet.css";
export default{
  name: "vmap",
  mounted: function(){
    // ・・・省略・・・
  },
  data: function(){
    // ・・・省略・・・
  },
  methods:{
    move(direction){
      this.offset = 0.005
      switch(direction){
        case "left":
        this.latlng = [this.latlng[0], this.latlng[1] - this.offset]
        this.map.panTo(this.latlng)
        break;
        case "up":
        this.latlng = [this.latlng[0] + this.offset, this.latlng[1]]
        this.map.panTo(this.latlng)
        break;
        case "right":
        this.latlng = [this.latlng[0], this.latlng[1] + this.offset]
        this.map.panTo(this.latlng)
        break;
        case "down":
        this.latlng = [this.latlng[0] - this.offset, this.latlng[1]]
        this.map.panTo(this.latlng)
        break;
      }
    }
  }
}
</script>

main.vue(親)

親コンポーネントでは,子コンポーネントのvmapタグにrefs属性を指定します. refs属性を指定することで,子コンポーネントのDOM要素を直接操作することができます. move メソッドでは,this.$refs.cmap で子コンポーネントを参照し, 子コンポーネントの move メソッドを呼び出しています.

<template>
  <div>
    <h1>Vue.jsで地図アプリ</h1>
    <vmap ref="cmap"></vmap>
    <vcontroller v-on:move-event="move"></vcontroller>
  </div>
</template>

<script>
import vmap from "./vmap"
import vcontroller from "./vcontroller"
export default{
  components:{
    vmap,
    vcontroller
  },
  methods:{
    move(direction){
      // 子コンポーネントであるvmap.vueのmoveメソッドを呼び出す
      this.$refs.cmap.move(direction);
    }
  }
}
</script>

下記のようにボタンをクリックすると,地図が東西南北に移動すれば完成です.

Image from Gyazo

参考書籍