Vue.js学習日記1(v-model, v-for, form@submit)

# Vue.js学習記録

今日から少しずつですがVue.jsの学習記録をつけていきます。自分用のメモみたいに書いているので少し読みにくい箇所は有ると思いますが、なるべく人に読んでもらう前提で書いていきますのでぜひ参考になれば幸いです。

筆者の学習歴は
・HTML&CSS
・Ruby on Rails(6.0)
・Javascript
・jquery


です。Ajaxを使ってアプリを実装する技術力が一通り身についたので次はVue.jsでもやってみようかなと思って学習を始めることにしました。
なので同じような状況の方がいればぜひ読んでいただきたいです。

### そもそもVue.jsってなによ？

JavascriptでUIを作るためのフレームワーク。なんか処理が速そう。

(公式サイト: https://jp.vuejs.org/)

ちなみに公式サイトは日本語に対応している。すごい！


### Vue.jsの読み込み

```vue
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
```

### dataとUIの結びつけを行う

```html
<div id="app">
    <p>Hello {{ name.toUpperCase() }}!</p>
    <p>
      <input type="text" v-model="name">
    </p>
</div>
```

普段見慣れているhtmlの中にnameとかtoUpperCaseとか変数やメソッドのようなものがある。これはVue.js独特の書き方で{{}}を使うことでJSの記述をhtmlにそのまま書くことができる。



実際jsではこんな感じで定義されている

```js
(function() {
  'user scrict';

  var vm = new Vue({
    el: "#app",
    data: {
      name: 'taguchi'
    }
  })

})();
```

このvar vmという変数にVueオブジェクトを用いてデータを生成している。Vueオブジェクトの中身は要素名とdataを指定する。dataはハッシュのような形で書くが、このときのキーが先程htmlで使用したキーと対応する。

もう一度htmlに戻る

```html
<div id="app">
    <p>Hello {{ name.toUpperCase() }}!</p>
    <p>
      <input type="text" v-model="name">
    </p>
</div>
```

inputタグに何やら見慣れないv-modelとかいう属性が有る。これはフォームに入力された値と先程のVueオブジェクト内のnameと結びつくようにできる。

挙動はこんな感じ
https://gyazo.com/ab3083138b07a16ff595642a64d2286f



こうすることでinputタグに入力した値が非同期でビューと結びつく。


### ループ処理の実装

jsで作成してVueオブジェクトに配列でデータを指定する場合を考える。以下のような形だ。

```js
(function() {
  'user scrict';

  var vm = new Vue({
    el: "#app",
    data: {
      todos: [
        'task 1',
        'task 2',
        'task 3'
      ]
    }
  })

  
})();
```

このとき、ビューにdataを表示する方法を考える。

やり方1

添字を使って表示する

```html
    <ul>
      <li>{{ todos[0] }}</li>
      <li>{{ todos[1] }}</li>
      <li>{{ todos[2] }}</li>
    </ul>
```

これでも確かに表示できるがもし要素が100個くらいになったとしたらちょっとしんどい。そこでループ処理を使う。

```html
    <ul>
      <!-- <li>{{ todos[0] }}</li>
      <li>{{ todos[1] }}</li>
      <li>{{ todos[2] }}</li> -->
      <li v-for="todo in todos">{{ todo }}</li>
    </ul>
```

li要素にあるv-for属性でループが実装できる。構文は

v-for="一つ一つのデータの名前 in 配列になっているdataのキーの名前"

こうすることで配列内の一つ一つの要素をtodoとして扱い、ビューで表示できる。
![My_Vue_App.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652172/4dcf33cf-40ac-16a5-4b35-633ef8e8577f.png)


その他の要素を追加して現状htmlはこんな感じ

```html
<div id="app">
    <h1>My Todos</h1>
    <ul>
      <li v-for="todo in todos">{{ todo }}</li>
    </ul>
    <form>
      <input type="text">
      <input type="submit" value="add">
    </form>
 </div>
```



### todoを追加できるようにする

ちょっと複雑になります。

【イメージ】

①フォームとtodos(配列)を紐付ける

②フォームを送った時にtodosにデータが追加されるようにする

③フォームの入力内容を空にする



こんな感じ

```html
<div id="app" class="container">
    <h1>My Todos</h1>
    <ul>
      <li v-for="todo in todos">{{ todo }}</li>
    </ul>
      <form @submit.prevent="addItem">
        <input type="text" v-model="newItem">
        <input type="submit" value="add">
      </form>
  </div>
```

form要素に@submitをつけるとsubmitしたときにjsで定義したメソッドを動かせる。.preventはpreventDefaultと同じ。

つまりこのformはsubmitしたときにaddItemメソッドを動かしますよ、という意味になる。

jsではこのように定義している。

```js
methods: {
      addItem: function() {
        this.todos.push(this.newItem)
        this.newItem = ""
      }
    }
```

ここは普通にjsだけど、thisというのがVueモデル内のdataを表している。pushはrubyのときみたいに配列に要素を追加する。

this.newItemは

先程のhtmlでinputタグに

```html
<input type="text" v-model="newItem">
```

v-modelを定義しているのでこの入力欄に入力された値のことを示している。こうすることでこのinputタグに入力した値をtodosに追加できる。ビューでループ処理を実装しているのでtodosに要素が追加されるたびに表示するtodoも増える。

挙動はこんな感じ
https://gyazo.com/6216d09add846f37132abc2b019b5b6c


※data側でnewItemを事前に定義しておく必要はあり、今回は初期値を""(空文字)にしている。railsでいうとマイグレーションファイルのdefault値みたいなイメージ。

```js
data: {
      newItem: '',
      todos: [
        'task 1',
        'task 2',
        'task 3'
      ]
    },
```