基礎からメモ: Vue.js CH5-p184 その他の機能やオプション
関数型コンポーネント
functional
オプションを付けることで、関数型コンポーネント(状態とインスタンスを持たない)を定義できる。
Vue.component('functional-component', { functional: true, render: function(createElement, context) { return createElement('div', context.props.message); }, props: { message: String } });
プリコンパイルを行わない場合は、文字列テンプレートではなく描画関数を使う必要がある。
単一ファイルコンポーネントの場合は、コンパイルされるので描画関数は要らない次の書き方ができる。
<template functional> <p>単一ファイルコンポーネントなら描画関数は要らない</p> </template>
動的なコンポーネント
特殊な属性is
でコンポーネントを指定することで複数のコンポーネントを切り替えることができる。
2種類のコンポーネントを定義
Vue.component('my-component-a', { template: '<div class="my-component-a">component A</div>' }); Vue.component('my-component-b', { template: '<div class="my-component-b">component B</div>' });
メインのコンストラクタ
var app = new Vue({ el: '#app', data: { componentTypes: ['my-component-a', 'my-component-b'], current: 0 }, computed: { component: function() { return this.componentTypes[this.current] } } });
<div id="app"> <div v-bind:is="component"></div> <button v-on:click="current^=1">toggle!</button> </div>
current^=1
でビット排他的論理和代入演算子を使って、ボタンを押すたびにcurrent
に1と0を交互に代入している。
Mixin
コンストラクタのオプションを抜き出して、コンポーネントに混ぜ込む機能。複数のコンポーネントで同一処理をする場合、Mixin
を使って共通化できる。
let mixin = { created:function() { this.hello() }, methods: { hello: function() { console.log('hello from mixin!') } } } Vue.component('my-component-a', { mixins: [mixin], template: '<div class="my-component-a">component A</div>' }); Vue.component('my-component-b', { mixins: [mixin], template: '<div class="my-component-b">component B</div>' });
keep-alive
で状態を維持する
コンポーネントのライフサイクル
コンポーネントのインスタンスにはそれぞれのライフサイクルがある。
v-if
ディレクティブでコンポーネントの描画状態が変わったり、動的コンポーネントで要素が切り替わったりすると、コンポーネントのインスタンスは破棄されライフサイクルが初期化される。先程の動的コンポーネントにMixin
を使った例では、要素が切り替わるたびにMixin
された要素のcreated
に登録された関数からメソッドが呼び出されるが、created
ライフサイクルフックはインスタンスの作成時にリアクティブ関係の初期化が終わったタイミングで呼ばれるので、切り替わるたびにライフサイクルが初期化されているのがわかる。
v-if
の記述場所による違い
コンポーネントのカスタムタグに書いたv-if
show
プロパティがfalse
になるとコンポーネントは破棄される。
<comp-child v-if="show"></comp-child>
コンポーネントのルートタグに書かれたv-if
コンポーネント内で自分自身のテンプレートのルートタグにv-if
がある場合、show
プロパティがfalse
になってもコンポーネントは破棄されない。
もしその内側に子コンポーネントがある場合、その子コンポーネントは破棄される。
<div class="child" v-if="show"> コンポーネントのテンプレート </div>
keep-alive
で状態維持
次の動的コンポーネントを使った例では、「メッセージ一覧」と「投稿フォーム」をボタンで切り替えるたびに、フォームに書き込んだ内容は消えてしまう。
<div id="app"> <button v-on:click="current='comp-board'">メッセージ一覧</button> <button v-on:click="current='comp-form'">投稿フォーム</button> <div v-bind:is="current"></div> </div>
Vue.component('comp-board', { template: '<div class="board">Message Board</div>' }) Vue.component('comp-form', { template: '<div class="form">Form<textarea v-model="message"></textarea></div>', data: function() { return { message: '' } } }) var app = new Vue({ el: '#app', data: { current: 'comp-board' }, });
この切り替わる部分に対して、要素をkeep-alive
タグで囲むと、フォームに入力した内容が保持されるようになる。
<keep-alive> <div v-bind:is="current"></div> </keep-alive>
keep-alive
が適用されたコンポーネントは、親コンポーネントが破棄されたときは保持された状態も一緒に破棄される。key
属性が設定されている場合はkey
ごとの状態を保持する。
keep-alive
で追加されるライフサイクルフック
keep-alive
が適用されたコンポーネントでは、活性化されたか非活性化されたかを判別するために次のライフサイクルフックが使える。
メソッド名 | タイミング |
---|---|
activated |
<keep-alive> を適用したコンポーネントが活性化したとき |
deactivated |
<keep-alive> を適用したコンポーネントが非活性化したとき |