Help us understand the problem. What is going on with this article?

体で覚えるVue.js - ディレクティブ編 〜 JSおくのほそ道 #023

More than 3 years have passed since last update.

こんにちは、ほそ道です。

今回も引き続きVue.jsのディレクティブを体で覚えます。
前回のビューモデル生成編同様、シンプルなサンプルに沢山触れる事でどんな道具があるのかをバンバン体験していくスタイルでやってまいります。

ViewModel生成編
ディレクティブ編
インスタンスメンバ編
グローバルメソッド編
フィルター編
v-repeatネスト編
全体の目次はこちら

ディレクティブ

ビューに記述するアレですね。
デザイナーさんは最低限ディレクティブさえ覚えておけば困る事はないはずです。
Vue.jsのディレクティブはデフォルトで「v-」という接頭辞がつきます。
それでは今回は気合いをいれて全部のディレクティブについてサンプルを作ってみたいと思いますので順繰りに見ていきましょう。

v-text

DOM要素の内側をテキストノードとしてすべて書き換える
{{property}}の形式もテキストノードとして変換され部分的な書き換えを行う場合はこちらを使うと良さそう

FOOとHelloBARを表示
<div id="sample">
  <div v-text="foo"></div>
  <div>Hello{{bar}}</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'FOO',
      bar: 'BAR'
    }
  });
</script>

v-html

DOM要素の内側をinnerHTMLとして書き換える
v-textはHTML文字列をただの文字列として解釈するが、v-htmlはHTMLとして扱う

v-text側は<p>FOO</p>を表示し、v-html側はFOOを表示する
<div id="sample">
  <div v-text="foo"></div>
  <div v-html="foo"></div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: '<p>FOO</p>'
    }
  });
</script>

v-show

参照する値がtrueとして評価され場合は表示し、falseとして評価される場合はdisplay:none等のスタイルが付いて非表示になる
要素の内側に値が表示される事は無い

fooを参照しているdivは表示され、barを参照しているdivは非表示になる
<div id="sample">
  <div v-show="foo" style="height: 100px; width:100px; background:red"></div>
  <div v-show="bar" style="height: 100px; width:100px; background:blue"></div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 1,
      bar: 0
    }
  });
  vm.bar = 1;  // ここで要素が表示される
</script>

v-class

2つの用法があり、引数無しの場合はバインドされた値がクラス名となる
引数ありの場合はバインドされた値がtrueと評価される場合だけクラス名が設定される

上のdivが引数なし、下のdivが引数あり(trueのデータを参照するクラスのみ設定される)
<div id="sample">
  <div v-class="foo, bar"></div>
  <div v-class="class1: t, class2: f"></div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'FOO',
      bar: 'BAR',
      t: true,
      f: false
    }
  });
</script>

v-attr

DOM要素の属性を設定する
属性の内部で{{property}}を設定した場合はv-attrとして扱われる

2つのやり方で属性を設定
<div id="sample">
  <div v-attr="style:foo">hosomichi</div>
  <div class="{{bar}}"></div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'font-size:30px',
      bar: 'BAR'
    }
  });
</script>

v-style

DOM要素のスタイルを設定する

スタイルをセット
<div id="sample" v-style="foo">hosomichi</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'font-size:30px',
    }
  });
</script>

v-on

DOM要素にイベントリスナーを登録する

クリックイベントを設定
<div id="sample" v-on="click: foo">ClickHere!</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    methods:{
      foo: function(){alert('clicked!');}
    }
  });
</script>

v-model

v-textと同様にDOM要素の内側をテキストノードとしてすべて書き換える
また編集可能な要素にセットする事でプロパティをリアルタイムで変更する事が出来るようになる

テキストボックスの編集に同期してdivのインナーテキストが変更される
<form id="sample" action="">
  <div v-text="foo"></div>
  <input type="text" v-model="foo">
</form>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'defaultValue',
    }
  });
</script>

v-if

バインドした値がtrue評価であればDOM要素が生成され、falseであれば破棄される
v-showと似ているがこちらは要素自体を生成/破棄する

vm.fooの値を書き換える事で表示/非表示が変化
<div id="sample">
  <div v-if="foo">Element</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data:{
      foo: false
    }
  });
  vm.foo = 1;  // ここで要素が表示される
</script>

v-repeat

DOM要素を繰り返し生成する事が出来る
バインドするデータはオブジェクトリテラルか配列のみ可能
配列の場合は$valueでアクセス出来る
オブジェクトリテラルの場合はキーが$key、値が$valueでアクセス出来る

配列をバインドするパターン
<div id="sample">
  <div v-repeat="foo">{{$value}}</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data:{
      foo: [100, 200,  300,  400,  500]
    }
  });
</script>
オブジェクトリテラルをバインドするパターン
<div id="sample">
  <div v-repeat="foo">{{$key}} = {{$value}}</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data:{
      foo: {
        a: 1,
        b: 2,
        c: 3
      }
    }
  });
</script>

v-view

DOM要素の内側をコンポーネントで置換する

ビューモデルのコンポーネントを使う(値の指定時にシングルクォートも必要な模様?)
<div id="sample">
  <div v-view="'foo'"></div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    components: {
      foo: {
        template: '<p>Custom View</p>'
      }
    }
  });
</script>
ex.グローバルコンポーネントを登録して使う
<div id="sample">
  <div v-view="foo"></div>
</div>
<script src="js/vue.js"></script>
<script>
  Vue.component('view1', {template: '<p>View Component</p>'} );
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'view1'
    }
  });
</script>

v-ref

componentのデータをビューモデルの$変数に登録できる

xとyをvm.$.fooに格納
<div id="sample">
  <div v-ref="foo" v-component="bar">value</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    components: {
      bar: {
        data: {
          x: 100,
          y: 200
        },
        template: '{{x}} and {{y}}'
      }
    }
  });
  console.log(vm.$.foo.x);
  console.log(vm.$.foo.y);
</script>

v-partial

DOM要素の内側をコンポーネントで置換する
クエリーセレクタで既存のDOM要素を引っ張ってくる事も出来る

クエリーセレクタとテンプレート的な使い方の両方を実行
<div id="sample">
  <div v-partial="foo"></div>
  <div v-partial="bar"></div>
</div>
<div id="other">other</div>
<script src="js/vue.js"></script>
<script>
  Vue.partial('foo', '#other');
  Vue.partial('bar', '<p>Partial</p>');
  var vm = new Vue({
    el: '#sample',
  });
</script>

v-effect

v-ifやv-showで要素の表示/非表示切替時にjavascriptを実行出来る
実行する関数はenterとleaveという名前で設定する

vm.barを変更する事でenter/leave関数が実行される
<div id="sample">
  <div id="inner" v-effect="foo" v-if="bar">inner</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      bar: false
    },
    effects: {
      foo: {
        enter: function(el, insert, timeout){
          insert();
          console.log('inserted');
        },
        leave: function(el, remove, timeout){
          remove();
          console.log('removed');
        },
      }
    }
  });
</script>

v-transition

CSSトランジションを使う要素である事を宣言する
v-ifやv-showと組み合わせて状態変化を描画する

ボタンクリックで表示/非表示をトランジションを適用させながら切替え
<style>
  .msg {
    transition: all .3s ease;
    height: 30px;
    padding: 10px;
    background-color: #eee;
    overflow: hidden;
  }
  .msg.v-enter,  .msg.v-leave {
    height: 0;
    padding: 0 10px;
    opacity: 0;
  }
</style>
<button onclick="vm.foo = vm.foo ? false : true">toggle</button>
<div id="sample">
  <p class="msg" v-if="foo" v-transition>Hello!</p>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: true
    }
  });
</script>

v-animation

CSSアニメーションを使う要素である事を宣言する
v-ifやv-showと組み合わせてアニメーションを描画する

ボタンクリックで表示/非表示をアニメーションを適用させながら切替え
<style>
  .msg { font-size: 30px; display: inline-block }
  .msg.v-enter { animation: fadein .5s; -webkit-animation: fadein .5s }
  .msg.v-leave { animation: fadeout .5s; -webkit-animation: fadeout .5s }
  @keyframes fadein {
    0% { transform: scale(0); }
    50% { transform: scale(1.5); }
    100% { transform: scale(1); }
  }
  @keyframes fadeout {
    0% { transform: scale(1); }
    50% { transform: scale(1.5); }
    100% { transform: scale(0); }
  }
  @-webkit-keyframes fadein {
    0% { -webkit-transform: scale(0); }
    50% { -webkit-transform: scale(1.5); }
    100% { -webkit-transform: scale(1); }
  }
  @-webkit-keyframes fadeout {
    0% { -webkit-transform: scale(1); }
    50% { -webkit-transform: scale(1.5); }
    100% { -webkit-transform: scale(0); }
  }
</style>
<button onclick="vm.foo= vm.foo? false : true">toggle</button>
<div id="sample">
  <span class="msg" v-if="foo" v-animation>Hello!</span>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: true
    }
  });
</script>

v-pre

v-preをつけた要素とその子要素はデータバインディングがスキップされる
スキップされた分描画は高速になる

下のdivは{{foo}}がそのまま画面に表示されてしまう
<div id="sample">
  <div>{{foo}}</div>
  <div v-pre>{{foo}}</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'hosomichi'
    }
  });
</script>

v-cloak

CSSの[v-cloak] { display: none}と組み合わせて使う事で
データバインディング完了までこのディレクティブがつけられた要素の描画は遅れさせられる
初期表示時の画面のちらつきを抑える効果がある

見た目にはわかりづらいがdisplay
<style>[v-cloak] { display:none }</style>
<div id="sample">
  <div v-cloak>{{foo}}</div>
</div>
<script src="js/vue.js"></script>
<script>
  var vm = new Vue({
    el: '#sample',
    data: {
      foo: 'hosomichi'
    }
  });
</script>

===

長かった…!!
今回は以上です。
次回は引き続きVue.jsで、Vueインスタンスのメンバを体で覚えます。

hosomichi
粋になりたい
fringe81
Fringeは、最新のテクノロジーとプロフェッショナルによるサービスにより、社会課題に仮説を立てて市場に広げていくことで、数十年という長期的なスパンで価値を生み出し続け、より良い世界を創る集団です。 既存の領域に限らず、時流を読み、仮説を生み出し、テクノロジーの力で優れたサービスを生み出し続けます。
https://www.fringe81.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away