Edited at

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

More than 1 year has 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インスタンスのメンバを体で覚えます。