【Vue.js】記法の違いまとめ

## はじめに


Vue.jsを勉強するにあたり、この書き方ってどう違うの？と思ったものをまとめました。
少しJavaScriptも混ざっていますが、お気になさらず。

## Q. `function()`を使う書き方とそうでない書き方は何が違うの？

```js
export default {
  methods: {
    // A
    method: function(arg) {
      console.log("メソッドAです")
    },

    // B
    method(arg) {
      console.log("メソッドBです")
    },
  },
};
```

### A. `method: function()`を短縮したものが`method()`です。

`method()`という記法はES2015(ES6)で導入された短縮形です。ES5では対応していません。
参考：[メソッド定義 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Method_definitions#Description)

## Q. `data`の表記がいろいろあるんだけど？

```js
export default {
  // A
  data: {
    name: "太郎",
    age: 10
  },

  // B
  data: function() {
    return {
      name: "太郎",
      age: 10
    };
  },

  // C
  data() {
    return {
      name: "太郎",
      age: 10
    };
  },
};
```

### A. コンポーネントで使う場合は関数にしなければなりません。

Aのパターンでは、以下参考サイトのようにコンポーネントでデータが独立しなくなってしまいます。そのため、少なくともコンポーネントではdataは関数（BかCの形）にする必要があります。BとCに違いについては前述のとおりです。

>コンポーネントの`data`オプションは関数でなければなりません。各インスタンスが返されるデータオブジェクトの独立したコピーを保持できるためです:
[コンポーネントの基本 — Vue.js](https://jp.vuejs.org/v2/guide/components.html#data-%E3%81%AF%E9%96%A2%E6%95%B0%E3%81%A7%E3%81%AA%E3%81%91%E3%82%8C%E3%81%B0%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93)

区別するのもややこしいので、基本的にすべて関数で書くようにすればいいと思います。
関数で書くデメリットはない気がします……。


## Q. `v-for`の`in`, `of`って使い分けとかあるの？
```vue
<div v-for="item of list">
<div v-for="item in list">
```

### A. ないです。

意味は全く同じなので、同じプロジェクト内で統一して使うようにすればいいと思います。

> 区切り文字として`in`の代わりに`of`を使用することができます。これは JavaScript のイテレータ構文に近いものです
[リストレンダリング — Vue.js](https://jp.vuejs.org/v2/guide/list.html)

イテレータ構文は以下のような書き方をします。

```js
for (variable of iterable) {
  statement
}
```

引用：[for...of - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for...of)


## Q. `props`の書き方は何が違うの？

```js
export default {
  // A
  props: ["name", "user"]

  // B
  props: {
    name: String,
    user: Object,
    },

  // c
  props: {
    name: {
      type: String,
      default: "",
      required: true,
    },
    user: {
      type: Object,
      default: () => {},
      required: true,
    },
  },
};
```

### A. 型を指定しているかどうかです。

- Aのパターン
  - 型を指定していないため、渡されたデータの型が何であろうと代入する。警告も出ない。
- Bのパターン
  - 型を指定しているため、違う型のデータが渡された場合は警告を表示する。
- Cのパターン
  - 型を指定し、かつデフォルト値を設定する。
  - Array, Objectのデフォルト値は関数で返す必要がある（いろんな人の書き方を見た感じではアロー関数の形が多かった）。
  - 必ず値が渡されるようになっている。


> コンポーネントはプロパティに対して、上で見たように型などの要件を指定することができます。もし指定した要件が満たされない場合、 Vue はブラウザの JavaScript コンソールにて警告します。
[プロパティ — Vue.js](https://jp.vuejs.org/v2/guide/components-props.html)

Object型を指定したuserに`"テキスト"`というString型を渡すと、以下のような警告が出ます。
（ただし一応表示される）

> [Vue warn]: Imvalid prop: type check failed for prop "user". Expected Object, got String with "テキスト".

また、propsに必ず値が渡される場合は`required: true`を付けておくよう推奨されています。値がうまく渡されていない場合は警告が出ます。


## Q. `this.name`と`name`って違うの？

### A. `<template>`内では同じものを示します。

テンプレート内では同一として扱われます。

```vue
<template>
  <div>
    {{ this.name }}
    {{ name }}
  </div>
</template>
```

ただし、メソッドについては以下のような挙動になります。

```vue
<template>
  <div>
    <button @click="showDialog"> <!-- 動く -->
    <button @click="showDialog()"> <!-- 動く -->
    <button @click="this.showDialog"> <!-- 動く -->
    <button @click="this.showDialog()"> <!-- 動かない -->
  </div>
</template>
```

一番下の書き方だとエラーが出ます。
> [Vue warn]: Error in v-on handler: "TypeError: Cannot read property 'showDialog' of null"


#### でも、普通thisは省略します。

テンプレート内では`this.name`ではなく`name`を使います。
v-onで使うメソッドは`showDialog`にし、引数がある場合のみかっこを付けます。

参考：[vue/this-in-template](https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/this-in-template.md)
　　　[vue/v-on-function-call](https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/v-on-function-call.md)


### A. `<script>`内では違うものを示します。

`this`が付いていないものは変数として認識します。当然ですね。

```js
export default {
  data() {
    return {
      name: "花子",
    }
  },
  methods: {
    showName() {
      const name = "太郎"
      console.log(this.name)  // "花子"
      console.log(name)   // "太郎"
    }
  }
}
```

## おわりに

ほとんどの内容が公式ページに書かれているので、公式は神です。
ご指摘、実際にはこんな風によく書くよ、などのご意見がございましたら、コメントをいただければ幸いです。