Vue.js メモ

Vue.jsを使えば、データを宣言的にDOM描画できる。宣言的とは、手続き的とは異なり、データをどうやって描画するのかという「手続き」を気にしない。その「手続き」はVue.jsの内部に隠蔽されている。使用者はデータの内容に集中することができる。

テンプレート構文

<div id="app">
  <span v-bind:title="msg">{{ text }}</span>
</div>
var app = new Vue({
  el: '#app',   //htmlの要素を指定して紐付ける
  data: {
    msg: '属性との紐付け' //テンプレートのv-bind:title="msg"と紐づく
    text: 'テキストの紐付け' //テンプレートの{{ text }}と紐づく
  }
})

条件分岐

  • v-if
  • v-else-if
  • v-else
  • v-show
<div id="app">
  <span v-if="error === 'A' ">エラーA</span>
  <span v-else-if="error === 'B' ">エラーB</span>
  <span v-else>OK!</span>
</div>
var app = new Vue({
  el: '#app',
  data: {
    error: 'B'
  }
})

Vue.jsが内部で要素の再利用をしている。そのため、v-ifv-elseで要素が再利用される可能性がある。これにより、input要素などでは入力欄の値が保持される可能性がある。これを回避するためには、要素のkey属性を付与し、一意な値に設定する。

v-showv-ifと同じ記述。v-showはCSSでの切り替えをする。そのため非表示時も描画される。

TIP

複数要素の表示を切り替えたい場合は、<template>を使用する。

<template v-if="error">
  <h1>エラー</h1>
  <p>エラー発生!!!!</p>
</template>

ただし、v-showでは<template>は使えない

ループ

<ul id="list">
  <li v-for="(item, index) in items" v-bind:title="item.title">
    {{ index }} - {{ item.msg }}
  </li>
</ul>
var list = new Vue({
  el: '#list',
  data: {
    items: [
      { title: 'オレンジ', msg: 'orange' },
      { title: 'ブルー', msg: 'blue' }
    ]
  }
});

TIP

key属性を指定して、DOM要素の状態の整合性を維持させることもできる。(内部でinput要素を使っているときなど)

<li v-for="item in items" v-bind:key="item.id">

WARNING

配列の内容を変更時、HTMLにも反映させるにはVue.set()を通して変更する。[]で変更すると反映されない。

Vue.set(list.items, index, newValue);

イベント

<div id="app">
  <button v-on:click="hello">Hello</button>
  <p>{{msg}}</p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    msg: ''
  },
  methods: {
    hello: function(event){
      this.msg += 'hello';
    }
  }
})

TIP

v-on:clickでメソッド呼び出しすれば、引数を渡すことができる。その際は$eventを明示的に渡すことでeventが使える。

<button v-on:click="hello('catalion', $event)"></button>
hello: function(name, event){
    this.msg += 'hello, ' + name;
}

修飾子が色々ある。

<!-- preventDefault() -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- preventDefault()とstopPropagation()  -->
<a v-on:click.stop.prevent="hello"></a>

<!-- 一度だけ -->
<a v-on:click.once="hello"></a>

<!-- Enter押下時のみ呼ぶ -->
<input v-on:keyup.enter="submit">

フォーム入力

<div id="app">
  <input v-model="msg">
  <p>メッセージ: {{ msg }}</p>
</div>
var app = new Vue({
  el: '#app'
  data: {
    msg: ''
  }
});

v-modelではIME変換中は反映されない。

他のinput要素

<div id="app">
  <input type="checkbox" id="single-check" v-model="checked">
  <label for="single-check">Check</label>
  <p for="single-check">{{ checked }}</p>

  <input type="checkbox" id="checkA" value="A" v-model="checkedNames">
  <label for="checkA">CheckA</label>
  <input type="checkbox" id="checkB" value="B" v-model="checkedNames">
  <label for="checkB">CheckB</label>

  <p>Checked names: {{ checkedNames }}</p>

  <input type="radio" id="radioA" value="A" v-model="checkedRadio">
  <label for="radioA">radioA</label>
  <input type="radio" id="radioB" value="B" v-model="checkedRadio">
  <label for="two">radioB</label>
  <p>checkedRadio: {{ checkedRadio }}</p>

  <select v-model="selected">
    <option disabled value="">選択してください</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
  </select>
  <p>Selected: {{ selected }}</p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    checked: false,
    checkedNames: ['B'],
    checkedRadio: '',
    selected: ''
  }
});

算出プロパティ

<div id="app">
  <p>Name: "{{ name }}"</p>
  <p>greet: "{{ greet }}"</p>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    name: 'catalion'
  },
  computed: {
    greet: function () {
      return 'Hello, ' + this.name;
    }
  }
})

getterとして使える。普通にメソッドを定義して呼び出すこととの違いは、算出プロパティはキャッシュされること。 上記の例の場合、name属性が変更されるまではgreetの結果はキャッシュされる。キャッシュされたくないならメソッドにする。

コンポーネント

Vueインスタンスを再利用可能な部品化したもの。独自のタグとして複数配置することができる。

<div id="app">
  <greet name="catalion"></greet>
  <greet name="トムソンガゼル"></greet>
</div>
Vue.component('greet', {
  //コンポーネントではdataは関数にする必要がある
  data: function () {
    return {
      msg: 'hello',
    }
  },
  //プロパティ。カスタム属性としてコンポーネントへデータを渡すことができる。
  props: ['name'],
  template: '<p>{{ msg }}, {{ name }}</p>'
});

var app = new Vue({
  el: '#app'
});

コンポーネントから親へのデータ送信はイベントを使う。

<div id="app">
  <task
    v-for="task in tasks"
    v-bind:key="task.id"
    v-bind:task="task"
    v-on:delete-task="deleted"> <!-- delete-taskイベントを受け取る -->
  </task>
</div>
Vue.component('task', {
  props: ['task'],
  template: `
    <div>
      <input type="checkbox" v-model="task.done">
      <span>{{ task.title }}</span>
      <button v-on:click="delete_task">削除</button>
    </div>
  `,
  methods: {
    delete_task: function(){
      //delete-taskイベントを発火、引数も渡せる
      this.$emit('delete-task', this.task);
    }
  },
});

var app = new Vue({
  el: '#app',
  data: {
    tasks: [
      { id: 1, title: 'コンビニで牛乳を買う', done: false },
      { id: 2, title: 'Vue.jsの勉強', done: false },
      { id: 3, title: 'ブログ記事を書く', done: false}
    ]
  },
  methods: {
    deleted: function(task){
      var index = this.tasks.findIndex(function(t){
        return t.id === task.id;
      });
      this.tasks.splice(index, 1);
      alert('タスク「' + task.title + '」を削除しました。');
    }
  }
});
Last Updated: 2018-5-23 17:47:18