Vue.js 入門 vol.3
参考サイト
https://jp.vuejs.org/v2/guide/class-and-style.html
クラスとスタイルのバインディング
<!-- isActiveがtrueの場合, classはactiveになる --> <div v-bind:class="{ active: isActive }"></div> <!-- hasErrorがtrueの場合、text-dangerが有効になる --> <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"> </div>
data: { isActive: true, hasError: false } //上記のようにデータを与えた場合以下のhtmlのコードのよな結果になる。
<!-- 上記のコードの結果 --> <div class="static active"></div>
- 以下のようにも表示可能
<div v-bind:class="classObject"></div>
data: { classObject: { active: true, 'text-danger': false } }
- 算出プロパティでもclassを制御可能。これが一般的ぽいぞ。
<div v-bind:class="classObject"></div>
//.. data: { isActive: true, error: null }, computed: { classObject: function () { return { active: this.isActive && !this.error, //isActiveがtrueで、errorが無い場合 'text-danger': this.error && this.error.type === 'fatal', } } }
配列構文
- v-bind:class にクラスのリストを適用する配列を渡すことができます
<div v-bind:class="[activeClass, errorClass]"></div>
data:{ activeClass: 'active', errorClass: 'text-danger' }
<!-- 上記のコードの結果 --> <div class="active text-danger"></div>
- 条件付きでリストを切り替える場合
<div v-bind:class="[isActive ? activeClass : '', errorClass]"> <!-- isActiveがtrueのときだけ、activeClassが適用される --> <div v-bind:class="[{ active: isActive }, errorClass]">
コンポーネントにおいて
- 以下のようなコンポーネントがあったとして、いくつかのクラスを追加してみる。
Vue.component('my-component', { template: '<p class="foo bar">Hi</p>' })
<my-component class="baz boo"></my-component> <!-- 結果として以下のhtmlが描画される --> <p class="foo bar baz boo">Hi</p>
- class bindingでも同様に機能する。
<my-component v-bind:class="{ active: isActive }"></my-component> <!-- activeがtrueの場合は、以下の通り --> <p class="foo bar active">Hi</p>
インラインスタイルのバインディング
オブジェクト構文
- v-bind:style はほとんどcssの文法に近い。
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: { activeColor: 'red', fontSize: 30 }
- templateをきれいにするために、styleObjectを作成するのもあり!
<div v-bind:style="styleObject"></div>
data: { styleObject: { color: 'red', fontSize: '13px' } }
- 配列構文もある。
<div v-bind:style="[baseStyles, overridingStyles]">
- 複数の値も配列で設定できる。
<div v-bind:style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">
条件付きレンダリング
- v-if を使う。
<h1 v-if="ok">Yes</h1> <h1 v-else>No</h1>
- v-if をグループに適用したい場合は、
<template>
を使う。最終的に描画される結果は、 要素は含まれません。すごい!
<template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template>
- v-elseは、v-ifの直後でないとだめ。
<div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div>
- v-else-if もある。
<div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div>
key による再利用可能な要素の制御
- 以下のコードで、logintypeを切り替えても、usernameで入力したvalueがそのまま残ってしまう。
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address"> </template>
- そのため、
Vue は”この 2 つの要素は完全に別個のもので、再利用しないでください”
と伝える必要がある。key属性を追加するだけ。
<template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email-address" key="email-input"> </template>
- v-show。v-ifとの違いは、v-showはtrueだろうが、falseだろうが、必ずDOMに維持される。
<h1 v-show="ok">Hello!</h1>
頻繁に何かを切り替える必要があれば v-show, 条件が実行時に変更することがほとんどない場合は、v-if を選びます。(v-ifのほうが、切り替えコストが高く(DOMの書き換えがあるため?)、v-showは、初期描画コストが高い(基本的に、すべてDOMに描画が維持されるため))
v-if と v-for : v-forは、v-ifより優先度が高い。
リストレンダリング
- v-for : item in items の形式で特別な構文を要求し、items はソースデータの配列で、item は配列要素がその上で反復されているエイリアスです(エイリアスは、シンボリックリンクと同義)
<ul id="example-1"> <li v-for="item in items"> {{ item.message }} </li> </ul>
var example1 = new Vue({ el: '#example-1', data: { items: [ { message: 'Foo'}, { message: 'Bar'} ] } }) // 結果 // Foo // Bar
- 配列を表示することも可能。
<ul id="example-2"> <li v-for="(item, index) in items"> {{ parentMessage }} - {{ index }} - {{ item.message }} </li> </ul>
var example2 = new Vue({ el: '#example-2', data: { parentMessage: 'Parent', items: [ { message: 'Foo'}, { message: 'Bar'} ] } })
- テンプレートでのv-for
<ul> <template v-for="item in items"> <li>{{ item.msg }}</li> <li class="divider"></li> </template> </ul>
- リストではなく、オブジェクトに対してもv-forを使って反復処理できる。(pythonでいうところの、辞書型か)
<ul id="repeat-object" class="demo"> <li v-for="value in object"> {{ value }} </li> </ul>
new Vue({ el: '#repeat-object', data: { object: { firstName: 'John', lastName: 'Doe', age: 30 } } })
- オブジェクト(辞書型)に対するv-forでは、key, indexもゲットできる。(順序は、Object.keys()の順番らしい。一貫性は保証されていないとのこと)
<div v-for="(value, key, index) in object"> {{ index }}. {{ key }} : {{ value }} </div>
- 範囲のv-for: 整数値も取ることができる。
<div> <span v-for="n in 10">{{ n }}</span> </div>
<my-component v-for="item in items" :key="item.id"></my-component>
<my-component v-for="(item, index) in items" v-bind:item="item" v-bind:index="index" v-bind:key="item.id" > </my-component>
- ToDoリストの例
<div id="todo-list-example"> <input v-model="newTodoText" *inputしたときに、valueを、newTodoTextに渡す v-on:keyup.enter="addNewTodo" * enterを押したときに、addNewTodoを実行する placeholder="Add a todo" * placeholderをセットする > <ul> <li is="todo-item" ※コンポーネントのimport v-for="(todo, index) in todos" ※ todosは、Vueのdataプロパティ のtodos v-bind:key="todo" ※コンポーネントに、todo(todosの中身)を渡す v-bind:title="todo" *コンポーネントの変数 titleに、todo(todosの中身)を渡す v-on:remove="todos.splice(index, 1)" * todosから削除する ></li> </ul> </div>
Vue.component('todo-item', { template: ` <li> {{ title }} <button v-on:click="$emit('remove')">X</button> </li> `, props: ['title'] }) new Vue({ el: '#todo-list-example', data: { newTodoText: '', todos: [ 'Do the dishes', 'Take out the trash', 'Mow the lawn' ] }, methods: { addNewTodo: function () { this.todos.push(this.newTodoText) this.newTodoText = '' } } })
- v-for と v-ifだと、v-forを優先する。以下のコードは、for ループしながら、if文で、completeしてないもののみ表示する。
<li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo }} </li>
- if文で条件分岐して、for文を使う場合は、wrapperされる要素にfor文を書く
<ul v-if="shouldRenderTodos"> <li v-for="todo in todos"> {{ todo }} </li> </ul>
- key は、for文の各要素を区別するために使うことができる。v-bindを使う。可能な場合はこれを使ったほうがいい。
<div v-for="item in items" :key="item.id"> <!-- content --> </div>
配列の変化を検出
- 配列の変更のメソッドは以下のものが使える。
push() pop() shift() unshift() splice() sort() reverse()
- 配列の置き換え
example1.items = example1.items.filter(function (item) { return item.message.match(/Foo/) })
- 注意事項: vueは配列で以下の変更を検出することができない。
// 1. インデックスでアイテムを直接設定するとき。例: vm.items[indexOfItem] = newValue // なので、以下のように設定する。 example1.items.splice(indexOfItem, 1, newValue) // 2. 配列の長さを変更するとき。例: vm.items.length = newLength example1.items.splice(newLength)
フィルタ/ソートされた結果の表示
- 算出プロパティ使うのが一番良さそう。
<li v-for="n in evenNumbers">{{ n }}</li>
data: { numbers: [ 1, 2, 3, 4, 5 ] }, computed: { evenNumbers: function () { return this.numbers.filter(function (number) { return number % 2 === 0 }) } }
- 算出プロパティが使えない場合は、メソッドも可。
<li v-for="n in even(numbers)">{{ n }}</li>
data: { numbers: [ 1, 2, 3, 4, 5 ] }, methods: { even: function (numbers) { return numbers.filter(function (number) { return number % 2 === 0 }) } }