【Vue.js】Vueの基本文法をまとめてみた

# Vueまとめパート1

こちらの記事は、Adnan Babakan 氏によりDev.to上で公開された『 Vue cheat sheet 1 』の邦訳版です（原著者から許可を得た上での公開です）

- 元記事：[Vue cheat sheet 1 ](https://dev.to/adnanbabakan/vue-cheat-sheet-1-194a)

原著をベースに説明の足りない部分は適宜、追記していく予定です。
（追記・改変の許可は得ています。）

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173746/cae737a3-498b-5f79-9d05-461a83ab6a99.png)

Dev.toコミュニティのみなさん、こんにちは！

私はVue.jsが大好きで書くのを楽しんでいます。この記事ではVue.jsのほぼすべての基本的な概念（公式Webサイトに基づく）を取り上げています。目次から必要なセクションに簡単にアクセスできます。

このパートではVueコンポーネントについては説明していません。

いくつかのコードサンプルは公式ウェブサイトから引用しています。[Vue.js](https://vuejs.org/guide/)で確認できます。[^1]

[^1]: 日本語版は[こちら](https://jp.vuejs.org/guide/)を参照

## `{{ }}` - 展開（Interpolation）
展開とは、VueのMustache構文(二重波括弧`{{ }}`)を使ってデータを画面にレンダリングすること。

### 単純な展開 
Mustache構文を使ってデータをレンダリングする。

```vue
<span>私の名前は{{ myName }}です。</span>
``` 

### 式を使った展開

Vueでは、展開に単純な式を含めることができる。

#### 単純な式展開
Mustache構文内でJavaScriptの式を使用可能。

```vue
<span>私は{{ myAge + 5 }}歳です!</span>
```   

JavaScriptのメソッドを使ってデータを操作し、レンダリングする文字列または整数を返すこともできる。

```vue
<span>私のペットたちの名前は{{ myPets.join(", ") }}です。</span>
```

#### 三項演算子を使った式展開
三項演算子を使用して、単純な条件付きレンダリングが可能。

```vue
<span>私は{{ myAge > 50 ? 'シニア' : 'シニアではない' }}です!</span>
```

_**注意**_：

*   Mustache構文内では1つの式しか使用できない

*   式（Expression）は文（Statement）とは異なる。たとえば、次のコードは、式ではなく文なので機能しない。 

```vue
<!-- これは誤り -->
{{ let msg = 'Hello World!'; }}
``` 

*   制御構文は、Mustache構文内ではサポートされていない。

```vue
<!-- これは誤り -->
{{ if (true) { return 'Yes!' } }}
```    

### 生のHTML展開

データをエスケープして実際のHTMLとしてレンダリングしたくない場合は、次の`v-html`ディレクティブを使うようにする。[^3]

[^3]: [訳注] 具体例は[こちら](https://jp.vuejs.org/v2/guide/syntax.html#%E7%94%9F%E3%81%AE-HTML)を参照

```vue
<span v-html="myHTMLData"></span>
```    

**_警告_**：HTMLのレンダリングは、WebサイトへのXSS（クロスサイトスクリプティング）攻撃を引き起こす可能性があるため、危険な場合がある。

## `v-bind` - バインディング（Binding）

バインディングとは、要素の属性に対してデータを使用すること。

###  単純なバインディング（Simple binding）
新米Vue開発者がやりがちなのは次のように属性にデータを入れようとすること。

```vue
<span class="{{ myClass }}"></span>
```    

しかし、これは間違いで実際にはデータをバインドしないといけない。

```vue
<span v-bind:class="myClass"></span>
```    

次のように、`:`だけで`v-bind`ディレクティブを省略して短く書くことができる。

```vue
<span :class="myClass"></span>
```    

### 文字列連結を使ったバインディング 
バインディングする際に文字列とデータを組み合わせる場合はどうするか。その場合は文字列を引用符で囲み、通常どおり連結する。

```vue
<span :class="myClass + 'test'"></span>
```    

これはハイパーリンク内で使うととても便利。

```vue
<a :href="baseURL + '/post/' + postId">さらに詳しく</a>
```    

これは、ベースURLと`post`サフィックス、post IDを含む投稿へのリンクの良い例。

### 条件付きバインディング （Conditional binding）

バインディングを使用して、条件付きで何かを行うことができる。

`disabled`や`required`のような値を持たない属性の場合、バインディングされたデータがtrueを返す場合はその属性が要素に追加され、falseを返す場合は属性は追加されない。

```vue
<button :disabled="true"></button>
```    

真偽値を返す式を使用することもできる。

```vue
<button :disabled="password.length < 6"></button>
``` 
 
条件が満たされた場合だけ指定したクラスをバインドするのに、クラス属性内でオブジェクトを使うことができる。

```vue
<div :class="{green: true, red: false}"></div>
```    

上記の例では、`div`要素に`red`ではなく`green`のclassが追加される。
比較演算子と論理演算子も使用できる。

次が使用例。

```vue
<div :class="{green: 5 > 1, red: false && 9 < 16}"></div>
```    

## `v-model` - 双方向データバインディング（Two-way data binding）
 
`v-model`ディレクティブを使うと、双方向のデータバインディングを実現できる。つまり、ユーザーは`input`を使用してデータを変更し、必要に応じて結果を同時に確認できる。

```vue
<input v-model="message" placeholder="メッセージを入力">
<p>メッセージ: {{ message }}</p>

let app = new Vue({
	el: '#app',
	data: {
		message: ''
	}
});
```

この`v-model`ディレクティブは、ほとんどすべての`input`タイプで機能する。

## `v-on` - イベント（Event）
イベントは、要素に対して特定のアクションが実行されたときに呼び出される。

イベントは`v-on`ディレクティブを使って宣言する。

```vue
<div id="app">
	<button v-on:click="callMyfunction"></button>
</div>


let app = new Vue({
	el: '#app',
	methods: {
		callMyfunction() {
			alert('This is it!');
		}
	}
});
``` 

このボタンをクリックすると、`callMyFunction`メソッドが呼び出される。
匿名関数も使うことができる。

```vue
<button v-on:click="() => alert('こんにちは！')"></button>
```    

`v-on`の省略形には`@`を使う。

```vue
<button @click="() => alert('こんにちは！')"></button>
```

## `[ ]` - 動的引数（Dynamic arguments）

属性名を評価させたい場合[^2]はどうするか。これは次のようにすることで可能。

[^2]: [訳注] 例えばVueインスタンスの`data`プロパティを使いたい場合など。JavaScript式の評価値を入れて動的に値を入れることができる。詳細は[こちら](https://jp.vuejs.org/v2/guide/syntax.html#%E5%8B%95%E7%9A%84%E5%BC%95%E6%95%B0)を参照

```vue
<div v-bind:[myAttribute]="myData"></div>
```    

イベント名を動的にアタッチすることもできる。

```vue
<div v-on:[myEvent]="doSomething"></div>
```    

### オブジェクトによる動的引数 
次のように、オブジェクトとJavaScriptのネイティブ動的キー構文を使用して動的引数をバインドする方法もある。

```vue
<button v-on="{[myAttr]: true}">可能な場合はクリック</button>


let app = new Vue({
	el: '#app',
	data: {
		myAttr: 'disabled'
	}
});
```

これはイベントにも使用可能。

```vue
<button v-on="{[myEvent]: function() { alert("Hello world!") }}">こんにちは！</button>


let app = new Vue({
	el: '#app',
	data: {
		myEvent: 'click'
	}
});
```
    

## `computed` - 算出プロパティ（Computed property）

算出プロパティ(`computed`)はコードを簡潔にする方法の１つ。算出プロパティはMustashe構文内などでJavaScript式の代わりに使うことができる。

次のコードがあるとする。

```vue
<p>
ベストなプログラミング言語：{{ programmingLanguages }}<br>
ワーストなプログラミング言語：{{ programmingLanguages.split(', ').reverse().join(', ') }}
</p>
```    

代わりに、次のような算出プロパティを定義して、`worstProgrammingLanguages`の代わりに使用できる。

```vue
<p>
ベストなプログラミング言語： {{ programmingLanguages }}<br>
ワーストなプログラミング言語： {{ worstProgrammingLanguages }}
</p>
```

```javascript
// ※言語の順位というのはは本当ではなくただの例えです
let app = new Vue({
	el: '#app',
	data: {
		programmingLangauges: 'JavaScript, C#, PHP, Python, LALALA, HOHOHO'
	},
	computed: {
		worstProgrammingLanguages() {
			return this.programmingLangauges.split(', ').reverse().join(', ');
		}
	}
});
```

算出プロパティはゲッターとして機能する。つまり、何かを返すだけで、データをセットする役割はない。

が次のようにこの動作を変更して、データに対する`set`メソッドと`get`メソッドの両方を設定できる。

```javascript
let app = new Vue({
	el: '#app',
	data: {
		myFirstName: 'Masa',
		myLastName: 'U'
	},
	computed: {
		myFullName: {
			get(): {
				return this.myFirstName + ' ' + this.myLastName;
			},
			set(v): {
				let parts = v.split(' ');
				this.myFirstName = parts[0];
				this.myLastName = parts[1];
			}
		}
	}
});
```

上記のコードは、文字列をスペースで分割し、データを設定しようとしているときに最初の部分をファーストネームとして、2番目の部分をラストネームとしてセットする。`myFullName`が、データを取得するときは名と姓が連結されている。

## `watch` - ウォッチャ（Watcher）

データがいつ変更されたかを知るためには一般的にウォッチャ（`watch`オプションで設定）を使う。

```javascript
let app = new Vue({
	el: '#app',
	data: {
		myAge: 19
	},
        // 設定されたプロパティ(監視プロパティ)をモニタリングして、変化があったときに働く
	watch: {
          myAge: function myAge(v) {
	    console.log('私は' + v + '歳です。');
	  }
	}
});
```    

_**注意**_：ウォッチャは、データ自体を操作しない（データの変化をモニタリングする）。

## `v-if` - 条件付きレンダリング

条件付きレンダリングは、いくつかの条件に従ってUIの一部を表示させたいときに使われる。これには`v-if/v-else`を使う。

```vue
<!-- isUserLoggedInの戻り値がtrueの時はHello userが表示される -->
<span v-if="isUserLoggedIn">Hello user</span>
<span v-else>Hi guest!</span>
```

条件には`v-else-if`も含めることができる。

```vue
<!-- 条件式の評価値によって表示される要素が変わる -->
<span v-if="favoriteColor === '赤'">赤い林檎</span>
<span v-else-if="favoriteColor === '青'">青い空</span>
<span v-else>うーん...</span>
```    

Vueはスマートで、異なるパーツのみを取り換える。
たとえば、Eメール、あるいはユーザー名でログインするための入力がある場合、条件によって2つの部分を切り替えても`input`要素を消去して再レンダリングしないため、ユーザーの入力値は削除されないままとなる。


```vue
<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>
```    

ただし、`key`を使用することで、これらのフィールドが完全に異なり再レンダリングする必要があることをVueインスタンスに伝えることが可能になる。

```vue
<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-show`を使って要素をレンダリングはするが非表示にすることができる（`v-show=false`の時は`display`プロパティを`none`にセットして非表示にしている）。

```vue
<span v-show="true">やあ!</span>
```    

_**注意**_：v-showは`<template>`要素に対しては使えない。`v-else`と一緒に使うこともできない。

**_注意_**：`v-if`は遅延描画である。つまり、最初にfalse状態のブロックはレンダリングされない。一方、`v-show`は実際にはレンダリングしているが、レンダリングされたブロックは非表示なっている。

## `v-for` - リストレンダリング(List rendering)
一連のデータのレンダリングは、他のプログラミング言語でのループに相当する。

これには`v-for`ディレクティブを使う。


### 配列に対して

多くの場合、配列を反復処理してレンダリングしたい場合がある。


```vue
<ul id="example-1">
  <li v-for="item in items">
	{{ item.message }}
  </li>
</ul>


var example1 = new Vue({
  el: '#example-1',
  data: {
	items: [
	  { message: 'Hoge' },
	  { message: 'Fuga' }
	]
  }
});
```

第２引数を渡して、現在のアイテムのインデックスにアクセスできる。

```vue
<ul id="example-2">
  <li v-for="(item, index) in items">
	{{ index }} - {{ item.message }}
  </li>
</ul>


var example2 = new Vue({
  el: '#example-2',
  data: {
	items: [
	  { message: 'Hoge' },
	  { message: 'Fuga' }
	]
  }
});
``` 

### オブジェクトに対して

オブジェクトのレンダリングは、配列のレンダリングよりも単純。

```vue
<ul id="v-for-object" class="demo">
  <li v-for="value in object">
	{{ value }}
  </li>
</ul>


new Vue({
  el: '#v-for-object',
  data: {
	object: {
	  title: 'How to do lists in Vue',
	  author: 'Jane Doe',
	  publishedAt: '2016-04-10'
	}
  }
});
```

第２引数を使用して、プロパティの名前にアクセスすることもできる。


```vue
<ul id="v-for-object" class="demo">
  <div v-for="(value, name) in object">
	{{ name }}: {{ value }}
  </div>
</ul>


new Vue({
  el: '#v-for-object',
  data: {
	object: {
	  title: 'How to do lists in Vue',
	  author: 'Jane Doe',
	  publishedAt: '2016-04-10'
	}
  }
});
```

オブジェクトを反復処理するときに、インデックスへのアクセスも利用できる。

```vue
<ul id="v-for-object" class="demo">
  <div v-for="(value, name, index) in object">
	{{ index }}. {{ name }}: {{ value }}
  </div>
</ul>


new Vue({
  el: '#v-for-object',
  data: {
	object: {
	  title: 'How to do lists in Vue',
	  author: 'Jane Doe',
	  publishedAt: '2016-04-10'
	}
  }
});
```

### 範囲に対して

数字の範囲を反復処理するのもとても簡単にできる。

```vue
    <div>
      <span v-for="n in 10">{{ n }} </span>
    </div>
```