vue.jsはじめました@超基礎編

最近業務でvueを触る機会が多いので備忘録として残します。

ここで記述しているvueのバージョンは2.5.16です。

v-onについて

v-onディレクティブはイベントリスナに加え、Vueインスタンスのメソッドを呼び出すことができます。

<button v-on:click="doSomething">Click</button>

<!--省略記法-->
<button @click="doSomething">Click</button>

v-onは省略できるのでコードを書く際には@イベントリスナ名としましょう。 慣れるまではv-onを書くことをすすめます。

v-modelについて

フォームの入力値をvue側のデータとバインドする「双方向データバインディング」を簡単に実現することができます。これがVue.jsの主要な機能とも言えます。

<div id="app">
  <input v-model="messgae">
  <p>{{messgae}}</p>
</div>
new Vue({
  el: "#app",
  data: {
    messgae: "Hello"
  }
})

上記のコードを載せたので試してみてください。

jsfiddle.net

inputタグの値が変更される度にバインドしたmessageが変更されていると思います。 v-modelがしていることは二つあります。

  1. inputタグにvue側のデータをバインドする
  2. イベントハンドリングをしてデータを更新している

1について下記のようにまずはHTML側とvueをバインドします。

<input v-bind:value="message">

2では下記のように値を更新しています。

まずinputイベントハンドラでユーザーが入力した値を取得します。

<input @input="message">

その後、vue側のデータ変数に実際にユーザーが入力した値を代入します。

this.message = e.target.value

v-onの仕組みは大事なのでここで何をしているかは言語化できるようにしましょう。

v-bindディレクティブについて

bindとは他動詞では〜を結びつけるという意味です。 Vue側のデータをDOMと結びつけることを意味します。 リアクティブにデータを更新したいときに使用します。

最も簡単な例はテキストとしてバインドする例です。

<div id="app">
  {{ message }}
</div>
new Vue({
  el: "#app",
  data: { message: "Hello Vue" }
})

二重のブランケットの場合はプレーンなテキストとして表示されます。 htmlタグとして認識させたい場合は、v-htmlというディレクティブを使用します。

<div id="app">
  <p v-html="message"></p>
</div>
new Vue({
  el: "#app",
  data: {
   message: "<h1 style='color:red;'>Hello, Vue!!!</h1>" 
  }
 
})

vueのバージョン1では、下記にように三重のブランケットにしてhtmlとして認識させるようにしていたみたいです。

<div id="app">
  {{{ message }}}
</div>

またHTML属性にバインドするケースも多いです。 例えばapiから受け取ったデータをテキストリンクとして表示させたいとき。

<a v-bind:href="itemLink">Google</a>
new Vue({
  el: '#app',
  data: {
    itemLink: "http://google.com"
  }
})

また省略記法としてv-bindの代わりに:属性名と書くことが多いので慣れておきましょう。

イベント修飾子

イベント修飾子は、クリックやキー操作などDOMイベントの変更をしたいときに使用します。 今回はその中でも.stop修飾子について説明したいと思います。

例えばモーダルがあるとします。

  • モーダルのコンテンツを覆っているDOM → modal
  • モーダルのコンテンツのDOM → modal_content
<div class="modal">
  <div class="modal_content"></div>
</div>

モーダルのコンテンツに何か入力フォームやクリックするものなどあったときに、同じイベントをハンドルした要素がネストしている場合、イベントの発生元であるe.target.valueから親要素へ向かって設定している要素のイベントが連鎖して行われます。 そのようなときにmodalにはクリックするとモーダルが非表示になるイベント、modal_contentにも入力フォームなどに入力するようなイベントを設定していると入力しようとしたときにモーダルが非表示になってしまいモーダルが閉じてしまいます。

このようなケースの場合など.stop修飾子を使用します。

まずは.stop修飾子をつけないで試してみます。

<div id="app">
  <div class="modal" @click="getClassinfo('modal')">
    modal
    <div class="modal_content" @click.stop="getClassinfo('modal_content')">
      modal_content
    </div>
  </div>
</div>
new Vue({
  el: '#app',
  methods: {
    getClassinfo: function(className) {
        console.log(className)
    }
  }
})

modal_contentをくりっくした出力結果が以下になります。

modal_content
modal

modal_contentがクリックされるたびにmodalのクリックイベントも発火しています。

今度は.stop修飾子をつけて、modal_contentをクリックしてみてください。

<div id="app">
  <div class="modal" @click="getClassinfo('modal')">
    modal
    <div class="modal_content" @click.stop="getClassinfo('modal_content')">
      modal_content
    </div>
  </div>
</div>

javascriptのコードは変わらないので省略します。

出力結果は以下のようになります。

modal_content

.stopをつけることでイベントの伝搬を止めたい箇所を指定できました。

親→子へ値を渡す方法

<div id="app">
   <child-component number="3"></child-component>
</div>

Vue.component('child-component', {
    template: `<div>{{number}}</div>`,
  props: ['number']
})
new Vue({
  el: '#app',
})

ここでは子コンポーネントである'child-componentpropsの値として1を渡しています。=の右辺の値が親が渡したい値であり左辺のnumberは子の方でpropsとして定義する必要があります。

子→親へ何かをするとき

子のコンポーネントの状態に応じて親コンポーネントに何かしてほしいとき、また子が持っているデータを親に渡したいときは$emitを使用します。

<div id="app">
    <div class="parents">
      <child-component @child-event="getData"></child-component>
    </div>
</div>
Vue.component('child-component', {
    template: `<div @click='giveData'>クリック</div>`,
  methods: {
    giveData(){
        this.$emit("child-event")
    }
  }
})
new Vue({
  el: '#app',
  methods: {
    getData(){
        console.log("受け取りました")
    }
  }
})

ここで大切になるのがカスタムイベントです。 $emitを使って任意のタイミング(ここではクリックをしたとき)でカスタムイベントであるchild-eventを発火させます。それを親側で受け取るためには親側でv-onを使って子のカスタムイベントをハンドリングします。

そしてchild-eventが発火したタイミング(クリックしたとき)で親で定義したgetDataが実行され下記のような出力結果になります。

受け取りました

上記では子のコンポーネントのイベントに応じて親のメソッドを実行してるだけでした。 では、子のコンポーネントから何かしらのデータを送ってみましょう。 htmlファイルは変更箇所がないので記述しません。

Vue.component('child-component', {
    template: `<div @click='giveData'>クリック</div>`,
  methods: {
    giveData(){
        this.$emit("child-event", "come from child-component")
    }
  }
})
new Vue({
  el: '#app',
  methods: {
    getData(message){
        console.log(message)
    }
  }
})

出力結果です。

come from child-component

$emitの第一引数にカスタムイベント名、第二引数に渡したいデータを追加してあげると子→親にデータを与えることができます。

今は決め打ちで値を渡してみましたが、子のコンポーネントで定義したdata属性のpersonsという中身がオブジェクトの集まりのデータを渡してみます。

Vue.component('child-component', {
    template: `<div @click='giveData'>クリック</div>`,
  data: function() {
    return {
    persons: [
        {name: "田中", age: 23},
        {name: "佐藤", age: 22},
        {name: "武田", age: 17}
      ]
    }
  },
  methods: {
    giveData(){
        this.$emit("child-event", this.persons)
    }
  }
})
new Vue({
  el: '#app',
  methods: {
    getData(persons){
        console.log(persons)
    }
  }
})

クリックするとconsole.log上にこのように子から親にデータが渡ってきていることがわかると思います。

(3) [{…}, {…}, {…}, __ob__: Observer]

上記のコードはこちらに書いたので試してみてください。

jsfiddle.net

今度はvue-class-componentsについて記事を書きたいと思います。