vue.jsの使い方の基礎＃１

久々にvueを触ったらわからな過ぎて「も～！」って言いすぎて牛になりました。
完全初心者としてリセットし、公式ドキュメント読みながらふ～んへ～と手を動かしていましたが復習と自分用教科書として書いていきます。アウトプットするとより一層覚えますよね。

書き方どうやってやんだっけってときに参考にしてくれる方がいたら超嬉しいです。

基本的に[[公式ドキュメント](https://jp.vuejs.org/v2/guide/#Vue-js-%E3%81%A8%E3%81%AF%EF%BC%9F)]やっていることは同じですのでそちらを見たほうが早いかもしれませんが。。。

ゼロからドキュメント読み進めて、実際にDBにつないだTODOをつくるまでまとめる予定ですのでよければ参考にしてください。vue基礎系の記事一覧はこちら（随時更新）


https://qiita.com/kty000/items/c919e01fc0c118098eb9


ドキュメントに沿って進めていきます（はじめに～テンプレート構文まで）

この記事ではファイル名を`sample.vue`としていますが、プロジェクト作成時の`App.vue`の内容を変えれば同様の動きになります。
コードの間違いや、私の説明で認識違い、もっとこう書いたほうがいいよ～などなどありましたらコメントで教えていただけると嬉しいです！

#宣言的レンダリング【{{ hoge }}】
>Vue.js のコアは、単純なテンプレート構文を使って宣言的にデータを DOM に描画することを可能にするシステムです

dataに入れた情報を表示してくれます。DBとってきた情報をdataにセットすれば動的に変えたりできるわけですね。
例えば関数でやんやして`message`の内容を変更したら、`message`が変わった時点で表示も自動で変わります。
以下のサンプルでは画面に「Hello!!vue.js:)」と表示されます。

```sample.vue
<template>
  <div id="app">
      <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
    data() {
        return {
            message: "Hello!!vue.js:)"
        }
    },
}
</script>
```

##JavaScript 式の使用
>実際には Vue.js は全てのデータバインディング内部で JavaScript 式を完全にサポートします:

`{{ }}`内にJavaScriptの式を書くことができます。
以下サンプルと実行結果

```sample.vue
<template>
  <div id="app">
      <p>{{ message }}</p>

      <p>{{ number + 1 }}</p>
      <p>{{ result ? 'YES' : 'NO' }}</p>
      <p>{{ message.split('').reverse().join('') }}</p>
  </div>
</template>

<script>
export default {
    data() {
        return {
            message: "Hello!!vue.js:)",
            number: 1,
            result: true
        }
    },
}
</script>
```
実行結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/302d2e3b-3c0b-0c46-cac0-a6025b754fd4.png)

###注意点1
>これらの式は、Vue インスタンスが所有するデータスコープ内で JavaScript として評価されます。制限として、それぞれのバインディングは、単一の式だけ含むことができるというものです

単一式は使えるけど以下のような式は使えないようです。

{{ var a = 1 }}
{{ if (ok) { return message } }} 

###注意点2
>テンプレート式はサンドボックスで、Math や Date といった ホワイトリストにあるグローバルオブジェクト だけにアクセスできます。テンプレート式内でユーザーが定義したグローバルオブジェクトにアクセスしようとしてはいけません。



#条件分岐【v-if】
条件一致の場合はこの文言を表示したいときに便利な書き方。
以下のサンプルでは画面に、「Hello!!vue.js:)」と「resultがtrue」が表示されます。
data内の`result`をfalseにすると「resultがtrue」は表示されません。

```sample.vue
<template>
  <div id="app">
        <p>{{ message }}</p>
        <p v-if="result">resultがtrue</p>
  </div>
</template>

<script>
export default {
    data() {
        return {
            message: "Hello!!vue.js:)",
            result: true
        }
    },
}
</script>
```

#ループ【v-for】
>アイテムのリストを配列内のデータを使って表示することができます

めっちゃ便利やん。。。例えば、従業員一覧とかを一覧で出すときに面倒な関数を書かなくても、データをJSONではいてセットすればOKってことです。（認識違ってたらすみません）
以下サンプルと実行結果

```sample.vue
<template>
  <div id="app">
        <p v-for="color in colors" v-bind:key="color.name">{{ color.name }}</p>
  </div>
</template>

<script>
export default {
    data() {
        return {
            result: true,
            colors:[
              {name: 'red'},
              {name: 'blue'},
              {name: 'yellow'}
            ]
        }
    },
}
</script>
```

実行結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/c19ecd79-a735-a92a-536f-ce272e2b7269.png)


##keyがないとエラーになる
最初以下のように書いていたらエラーが出た

```sample.vue
<template>
  <div id="app">
        <p v-for="color in colors">{{ color.name }}</p>
  </div>
</template>

<script>
export default {
    data() {
        return {
            result: true,
            colors:[
              {name: 'red'},
              {name: 'blue'},
              {name: 'yellow'}
            ]
        }
    },
}
</script>
```

エラー内容
`error  Elements in iteration expect to have 'v-bind:key' directives  vue/require-v-for-key`

key属性が必要ってもう少し後のほうのドキュメントに書いてありました。なるほど～

https://jp.vuejs.org/v2/guide/list.html#%E7%8A%B6%E6%85%8B%E3%81%AE%E7%B6%AD%E6%8C%81

#ユーザー入力の制御【v-on】

>v-on ディレクティブを使ってイベントリスナを加え、Vue インスタンスのメソッドを呼び出すことができます

イベントリスナを加えるの楽になりそうですね。
以下サンプルです。ボタンをクリックしたら、表示される文字が「こんにちは」から「ボタンを押しました」に代わります。
宣言的レンダリングでも説明しましたが、`message`が変わった時点で表示も自動で変わります。DOMをやってくれるのはとっても助かりますね。

```sample.vue
<template>
  <div id="app">
      <p>{{ message }}</p>
      <button v-on:click="changeText()">ボタン</button>
  </div>
</template>

<script>
export default {
    data() {
        return {
            result: true,
            message: "こんにちは"
        }
    },
    methods:{
      changeText(){
        this.message = "ボタンを押しました"
      }
    }
}
</script>
```

##動的引数
>バージョン 2.6.0 から、角括弧で囲むことで JavaScript 式をディレクティブの引数に使うこともできます

よくわからないので公式を参考に書いてみた。
以下サンプルです。先ほどのコードと同じくボタンをクリックしたら、表示される文字が「こんにちは」から「ボタンを押しました」に代わります。

```sample.vue
<template>
  <div id="app">
      <p>{{ message }}</p>
      <button v-on:[event]="changeText()">ボタン</button>
  </div>
</template>

<script>
export default {
    data() {
        return {
            message: "こんにちは",
            event: "click"
        }
    },
    methods:{
      changeText(){
        this.message = "ボタンを押しました"
      }
    }
}
</script>
```

`v-on:click="changeText()"`では、クリックされたら`changeText()`のメソッドを呼んでねという書き方。
今回の`v-on:[event]="changeText()"`では、なんかしらのイベントが起こったら`changeText()`のメソッドを呼んでね。なんのイベントかはdataの`event`を参照してねという書き方。

のちのちコードを変えたりする可能性も加味して使い分けるのがよさそうですね。その使い分けが難しいんだけどね。

##省略記法
以下のように省略して書くことができます。
便利だけど複数人で開発するときは記法のルールを決めたほうがコードが美しくなりそう。

```sample.vue
<!-- 完全な構文 -->
<button v-on:click="changeText()">ボタン</button>

<!-- 省略記法 -->
<button @click="changeText()">ボタン</button>

<!-- 動的引数の省略記法 (2.6.0 以降) -->
<button @[event]="changeText()">ボタン</button>
```

超余談ですが、すべて独学なのでコードがあまり綺麗くなかったんですが、リーダブルコードという本を読んだらほ～！ってなりました。劇的改善！とまではいかないけど書き方を考えるようになりました。ありがとうオライリー。
#双方向バインディング【v-model】
vueがもつ情報（以下サンプルだとmessage）とアプリケーション状態（以下サンプルだと入力のフィールド）のバインディング（結びつけ）ができます。
以下サンプルと実行結果

```sample.vue
<template>
  <div id="app">
      <p>{{ message }}</p>
      <input type="text" v-model="message"/>
  </div>
</template>

<script>
export default {
    data() {
        return {
            message: "こんにちは"
        }
    }
}
</script>
```
実行結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/91940868-0936-6f01-c900-9df241a6e55c.png)
入力フィールドと、表示の文言が連動しています。
フィールドの内容をかえると文言も変わります。
![キャプチャ.1PNG.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/81cd4022-1e75-5201-35c8-1cc7dc2fcfde.png)

#コンポーネント化
コンポーネントについてはちょっと長くなってしまったので別の記事にしました。良ければそちらを見てみてください！

https://qiita.com/kty000/items/2236e96b1bf56fc79ddd


#v-onceディレクティブ
>データ変更時の更新はおこなわず、一度だけ展開することができます

何度も書いてますが`{{ hoge }}`を利用した場合、データが変われば表示も変わりますよね。この表示を１回したらあとは変えないぞ！というときに使います。画面表示時に最初のバインディングが行われて、それ以降は静的になります。

`v-on`の時に使用したコードに`v-once`を追加してみます。

```sample.vue
<template>
  <div id="app">
      <p v-once>{{ message }}</p>  ----ここにv-onceを追加
      <button @click="changeText()">ボタン</button>
  </div>
</template>

<script>
export default {
    data() {
        return {
            result: true,
            message: "こんにちは"
        }
    },
    methods:{
      changeText(){
        this.message = "ボタンを押しました"
      }
    }
}
</script>
```

実行してボタンを押しても、「こんにちは」のまま変わらなくなりました。

#生のHTMLを出力【v-html】
dataに生のHTML文をセットして表示させることができます。
そのまま`{{ }}`を使用すると、プレーンなテキストとして扱われるので、`v-html`を使用する必要があります。
以下サンプルと実行結果


```sample.vue
<template>
  <div id="app">
      <p>{{ sampleHtml }}</p>
      <p v-html="sampleHtml"></p>
  </div>
</template>

<script>
export default {
    data() {
        return {
            sampleHtml: '<span style="color:red">HTML文です</span>'
        }
    }
}
</script>
```

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550109/66809a3c-5fb3-398d-0c33-1b3b7422af7a.png)

##補足
>この p のコンテンツは sampleHtml プロパティの値に置き換えられ、プレーンな HTML として解釈されます。Vue は、文字列ベースのテンプレートエンジンではないので、v-html をテンプレート部品を構成して使用できないことに注意しましょう。代わりに、 UI の再利用や組み合わせのための基礎として、コンポーネントを利用することが好ましいです

`v-html`を使用する場面があまり思い浮かばないのですが、何度も使用するためdata化するならコンポーネントで作ったほうがいいよってことみたいです。

>XSS 脆弱性を容易に引き起こすので、ウェブサイトで動的に任意のHTMLを描画することは、非常に危険です。信頼できるコンテンツにだけ HTML 展開を利用してください。ユーザーから提供されたコンテンツに対しては決して使用してはいけません。

こんな記載もありました。たしかにウェブで展開すると、悪い人がサイトに飛ぶはずのボタンをウイルス流すボタンに変えちゃったり、、、しかも見た目は変わらない、、、みたいなことがありうるのかな？よっぽどのことがない限り使わないほうがいい気がします。


ドキュメントすべて１つの記事でまとめると書くのも読むのも大変なので、つづきはまた別の記事で書ければと思います。
読んでくれてありがとうございます！