【Vue】ディレクティブ(イベント)

Vueではhtmlに対してディレクティブと呼ばれる属性形式の命令を付与することで、ページに機能を付与している

<!-- v-で始まる属性 -->
<a v-bind: href="url">...</a>

ディレクティブは用途に応じて以下のように分類できる

分類 概要 主なディレクティブ
データバインド 式の値をページに反映 v-bind, v-htmlなど
イベント イベント処理を実装 v-on
フォーム フォームからの入力を取得 v-model
制御 条件分岐や繰り返し処理など v-if, v-forなど

イベント関連のディレクティブ

以下のコートでは①のv-onディレクティブでイベントハンドラを設定し、クリックされたときに②を呼び出している

<div id="app">
  <button @click="onclick">クリック</button>  <!-- ① -->
  <p>{{ message }}</p>
</div>
new Vue({
  el: '#app',
  data: {
    message: '',
  },
  methods: {
    // クリック時に現在時刻を取得…②
    onclick: function () {
      this.message = new Date().toLocaleString()
    },
  },
})

また、v-onはよく利用することから省略構文が用意されている

<button @click="onclick">クリック</button>
イベントオブジェクト

イベントオブジェクトを利用することで、イベントに関する情報にアクセスしたり、イベントハンドラーの挙動を操作したり(キャンセルなど)といったことが可能になる

  <div id="app">
    <button v-on:click="onclick">クリック</button>
  </div>
new Vue({
  el: '#app',
  methods: {
    // クリック時にイベントオブジェクトをログに出力
    // テンプレートからの値とイベントオブジェクトを同時に受け取りたい場合は(arg, $event)と書く
    onclick: function (e) {
      console.log(e)
    },
  },
})

【Vue】リアクティブデータ

Vueクラスのdataオプションに登録されたデータは変更があれば自動的にページに反映される

以下のコードを実行すると現在時刻が表示され、1秒毎に更新される

<div id="app">
    <p>現在時刻:{{ current.toLocaleString() }}</p>
</div>
new Vue({
  el: "#app",
  data: {
    // 現在時刻
    current: new Date(),
  },
  //始動時にタイマーを設定
  created: function () {
    let that = this;
    // 1000ミリ秒スパンでcurrentプロパティを更新
    this.timer = setInterval(function () {
      that.current = new Date();
    }, 1000);
  },
  beforeDestroy: function () {
    clearInterval(this.timer);
  },
});

※あとから破棄できるように生成したタイマーはtimerプロパティに格納しておく

プロパティの追加・削除

Vue.jsはJavaScriptの制約によりプロパティそのものを追加・削除することができない
この問題を避けるには以下の手段がある

  1. 全てのプロパティを最初に準備する
  2. Vue.setメソッドを利用する

ビューの非同期更新

リアクティブシステムによるビューの更新は非同期であり、連動して発生するすべての変更をプールした上で最終的な結果を反映する
ビューへの反映の完了を待ってから何かしらを実行するには$nextTickメソッドを利用する

this.$nextTick().then(function() {
  // 何かしらの処理
});

ウォッチャーによる監視

例えばフォームへの入力を監視して入力の間隔が空いたときだけ処理を実行したり、変更を検知して非同期通信を行うなど標準的なリアクティブシステムだけでは対応できないことをやりたい場合はwatchオプションを利用する

watch: {
  hoge: function(newValue, oldValue) {
    // 何かしらの処理
  }
}

またウォッチャーには動作オプションを定義できる

オプション 概要
handler ウォッチャーの本体
deep 入れ子のオプションも監視するか
immediate 起動時に即座に実行するか

【Vue】Vueの基礎

Vue.jsの基礎となる3つのしくみについて書いていく

  1. ディレクティブ
  2. 算出プロパティおよびメソッド
  3. ライフサイクルフック

1. ディレクティブ

テンプレートに属性やスタイルの操作、条件分岐、繰り返し処理など、より複雑な機能を組み込みたい場合は、ディレクティブ(v-****)を利用する
コロンの後方はディレクティブの引数(ディレクティブによっては引数を受け取るものがある)

<!-- urlはjs側のdataオプションで用意 -->
<a v-bind:href="url">リンク</a>

v-bind
属性値にJavaScriptの値を埋め込む
v-bindはよく利用するため省略構文が用意されている

<a :href="url">リンク</a>

checkd、selected、disabledなど、値が要らない属性(属性名を指定するだけで意味がある属性/論理属性)に値をバインドするにはtrueまたはfalseを用いる

<!-- flagはjs側のdataオプションで用意 -->
<input type="button" value="クリック" v-bind:disabled="flag" />

2. 算出プロパティ

算出プロパティとは既存のプロパティを算出した結果を取得するためのゲッターで、computedオプション配下にハッシュ形式で書く
例えばemailプロパティの@より前だけ取り出して表示したい場合、以下のように書く

    <div id="app">
        <p>{{ localEmail }}</p>
    </div>
new Vue({
  el: "#app",
  data: {
    email: "xxxx@hoge.com",
  },
  computed: {
    localEmail: function () {
      return this.email.split("@")[0].toLowerCase();
    },
  },
});
メソッドによるロジックの切り出し

メソッドを使って書き換えると以下の書き方になる(ほぼ同じ意味)

    <div id="app">
        <p>{{ localEmail() }}</p>
    </div>
new Vue({
  el: "#app",
  data: {
    email: "xxxx@hoge.com",
  },
  methods: {
    localEmail: function () {
      return this.email.split("@")[0].toLowerCase();
    },
  },
});
算出プロパティとメソッドの違い

同じような使い方もできるが異なる点もある

  • 算出プロパティは引数を持てない
  • 算出プロパティの用途は基本的に既存データの加工を伴う取得であり、クリックイベントの処理などはメソッドの役割
  • 算出プロパティの値はキャッシュされる(算出プロパティが自身が依存するプロパティ(this.***)が変更された場合にのみ評価されるのに対し、メソッドは再描画のたびに評価される)

3. ライフサイクルフック

Vueインスタンスは、最初に生成された後、要素にマウントされて、データの変化に応じてビューを更新させていき、最終的に破棄される
この一連の流れはライフサイクルと呼ばれる
Vue.jsにはライフサイクルの変化に応じて呼び出されるメソッドが用意されている(ライフサイクルフック)
このうちよく使われるのはcreated、mount、beforeDestroy

メソッド名 概要
beforeCreate インスタンスが初期化されるときに呼ばれる
created インスタンスが作成された後に呼ばれる
beforeMount マウンティングが開始される直前に呼ばれる
mounted インスタンスがマウントされた後に呼ばれる
beforeUpdate データが更新された後、再描画前に呼ばれる
updated データが更新された後、再描画後に呼ばれる
activated 生き続けたコンポーネントが活性化するとき呼ばれる
deactivated 生き続けたコンポーネントが非活性化するとき呼ばれる
beforeDestroy Vueインスタンスが破棄される直前に呼ばれる
destroyed Vueインスタンスが破棄された後に呼ばれる
errorCaptured 任意の子孫コンポーネントからエラーが捕捉されるときに呼ばれる

以下のように利用する

new Vue({
  el: "#app",
  beforeCreate: function () {
    console.log("beforeCreate...");
  },
  created: function () {
    console.log("created...");
  },
...

【Vue】Vueとは

JavaScriptフレームワークのVueについて勉強し始めたのでメモ

Vueの特徴
  • コンポーネント指向
  • 仮想DOMを利用している
  • ルーティングやグローバルの状態管理は関連ライブラリに担当させている
  • プログレッシブに導入できる
導入方法(選択肢は3つ)
  • CDN経由でライブラリをインポート
  • npmを利用してインストール
  • Vue CLIでプロジェクトを構築

以下はCDN経由でのインポート(バージョン2.6.14の場合)
※vue.jsはデバッグ用のファイルでファイルサイズが大きいため、本番環境ではvue.min.jsに置き換える

<body>
    <!-- ここにページ本文 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <script src="../js/life.js"></script>
</body>

ブラウザにhello, world!を表示するには以下のように書く

hello.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title></title>
</head>

<body>
  <div id="app">
    <p>{{ message }}</p>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
  <script src="./hello.js"></script>
</body>

</html>

hello.js

let app = new Vue({
  el: "#app",
  data: {
    message: "hello, world!",
  },
});
基本的な構文

Vue.jsの核となるのはVueクラス

new Vue({...})

Vueインスタンスの引数にはoption: value,...のハッシュ形式で動作オプションを指定できる

hello.jsで利用しているのは以下

let app = new Vue({
  el: "#app", // el: Vue.jsを適用する要素
  data: { // data: データオブジェクト
    message: "hello, world!",
  },
});

elオプション
このコードではelを#appとしているので、html側でid="app"の要素の配下でVue.jsが有効になる
Vue.jsが管理する範囲を限定するという意味でもhtmlタグやbodyタグを対象にするのは避けた方が良い

dataオプション
dataオプションはテンプレートから参照できる値を格納したオブジェクト

データオブジェクトへのアクセス

テンプレートからオブジェクトにアクセスするには{{...}}を用いる(マスタッシュ構文)
なお{{...}}で利用できるのは式のみ

<p>{{ message }}</p>