「これからはじめるVue.js実践入門」の感想・備忘録4

スポンサーリンク
「これからはじめるVue.js実践入門」の感想・備忘録3の続き

コンポーネント(応用)

<component>要素

  • コンポーネントの入れ物であり、コンポーネントを動的に切り替えることができる。
  • タブで表示内容を切り替える場合などに便利。

定義

components: {
  'my-component1': { template: `<p>my-component1</p>`, },
  'my-component2': { template: `<p>my-component2</p>`, },
},
data: { index: 1, },
created: function() {
  this.interval = setInterval(() => {
    this.index = (this.index % 2) + 1
  }, 1000)
},
beforeDestroy: function() { clearInterval(this.interval); }

呼び出し

<component v-bind:is="`my-component${index}`"></component>

使い方

  • 表示するコンポーネント名をv-bind:is="xxx"で指定する。
  • input要素などがある場合、入力内容はコンポーネント切り替え時に破棄されてしまう。
  • <component>要素を<keep-aliove>で囲むと、コンポーネントがキャッシュされ入力内容が消えなくなる。
    <keep-aliove>要素は、max属性でキャッシュの最大数、include, exclude属性でキャッシュするしないをコンポーネント名で指定することができる。

自作のコンポーネントでのv-modelの利用

  • コンポーネント間のデータ交換は、プロパティと$emitを使うのが基本だが、v-modelを自作のコンポーネントで利用することもできる。
  • ただし、コンポーネントにvalueプロパティを用意し、それを配下のinput要素などにバインドし、inputイベントを$emitしなければならない。

定義

'my-input': {
  template: `<p><input type="text" v-bind:value="value" v-on:input="$emit('input', $event.target.value)"></p>`,
  props: ['value'],
},

呼び出し

<my-input v-model="msg"></my-input>{{ msg }}
これは <my-input v-bind:value="msg" v-on:input="msg=$event"></my-input>{{ msg }} と同じ意味である。

input以外のイベントを使う場合

  • デフォルトではv-modelはvalueプロパティとinputイベントに紐づく。
  • 変更したい場合は、modelオプションでpropとeventを指定する。
'my-input': {
  template: `<p><input type="text" v-bind:value="name" v-on:input="$emit('change', $event.target.value)"></p>`,
  props: ['name'],
  model: {
    prop: 'name',
    event: 'change'
  }
},

.syncs修飾子による複数プロパティの双方向バインディング

  • v-bindの.sync修飾子はv-modelと同じ機能を提供する。
  • v-modelと.sync修飾子は同じ役割を持つが、単一の場合はv-modelを使えばよい。
    双方向バインディングが必要なプロパティが複数ある場合のみ.sync修飾子を使う。

定義

'my-input': {
  template: `<p><input type="text" v-bind:value="text1" v-on:input="$emit('update:text1', $event.target.value)"></p>`,
  props: ['text1'],
},

呼び出し

<my-input v-bind:text1.sync="msg"></my-input>{{ msg }}

使い方

  • propsにxxxを定義し、v-bind:value="xxx" v-on:input="$emit('update:xxx', $event.target.value)"とする。
  • v-bind:xxx.sync="yyy"で呼び出す。

アニメーション

<transition></transition>の直下の要素(単一でなければならない)は、描画切り替え(v-if, f-show)のタイミングでアニメーション用のクラスが付与される。]

  • アニメーション前:.v-enter, v-leave
  • アニメーション後:.v-enter-to, .v-leave-to
  • 変化の度合いや時間の指定:.v-enter-active, .v-leave-active
  • 他にもリストの追加・削除・ソート時のアニメーションも可能だが、ここでは省略する。
<transition>
  <div class="panel" v-show="flag">アニメーションテスト</div>
</transition>
<p><button v-on:click="flag=!flag">表示/非表示</button></p>

<style>
.panel {
  width: 300px;
  height: 200px;
  border: solid 1px #000;
  background-color: #00b8d4;
}
.v-enter,
.v-leave-to {
  height: 0px;
}
.v-enter-to,
.v-leave {
  height: 200px;
}
.v-enter-active,
.v-leave-active {
  transition: height 3s;
}
</style>

Element

Vue.jsで利用できるコンポーネントライブラリ。

<!-- 読み込み -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/element-ui@2.14.0/lib/umd/locale/ja.js"></script>

<!-- Button -->
<button type="button" class="el-button el-button--primary">Primary</button>
<!-- Transfer -->
<el-transfer v-model="transferValue" :data="transferData" v-bind:titles="['選択元', '選択先']"></el-transfer>

<script>
ELEMENT.locale(ELEMENT.lang.ja);
const app = new Vue({
  el: '#app',
  data: {
    transferValue: [],
    transferData: [{key: 1, label: 'りんご'}, {key: 2, label: 'みかん'}, {key: 3, label: 'ぶどう'}]
  },
})
</script>

ミックスイン

  • 複数のコンポーネントで同一のコードが存在する場合、ミックスインとして共通コードを抜き出すことでコンポーネントに動的に適用できるようになる。
  • ミックスインはオブジェクトリテラルであり、data, methods, computed,ライフサイクルフックなどコンポーネントで利用できる全てのオプションを利用できる。
  • ミックスインの名前は〜ableとすると内容がわかりやすくなる。

定義

const mixinTest = {
  mounted() {
    console.log(this.$data);
  },
}

コンポーネントへの適用

  • mixinsオプションに配列で指定する。
  • コンポーネントとミックスインでオプションが競合した場合
    • data, methods, computedなどはマージされる。
    • dataに同じキー名が存在する場合はコンポーネント側が優先される。
    • ライフサイクルフックは、ミックスイン⇒コンポーネントの順番で実行される。
  • グローバルミックスイン Vue.mixin()で全てのコンポーネントに適用させるグローバルミックスインを定義することもできるが、アプリ全体に影響が及ぶためあまり使用するべきではない。
<script>
new Vue({
  el: '#app',
  components: {
    'my-mixin': {
      template: `<p>my-mixin</p>`,
      data() {
        return {
          hoge: 'hoge',
        }
      },
      mixins: [mixinTest],
    },
  }
});
</script>

コメント