Vueのことはじめ色々

# viteプロジェクト（デモプロジェクト）を作成

```
yarn create vite
```

package.json内 scriptsセクションのコマンドを実行

```:localhostでページを開く
yarn dev
```


# Vueプロジェクトの構成

`App.vue`：サンプルページの描画を行う

```typescript:main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

createApp(App).mount('#app') // index.htmlのappタグの付いた部分にApp.vueを挿入
```

```html:index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + Vue + TS</title>
  </head>

  <body>
    <div id="app"></div> // app.vueが挿入される
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
```

# Vueファイルの構成

- script
    - javascriptを記載するセクション
    - templateセクション内で参照する
- template
    - htmlを記載するセクション
- style
    - CSSを記載するセクション
    - 独自クラスの定義も可能
    - `<style scoped></script>`で他のVueファイルとsytleを共有しなくなる

```vue:example
<script setup lang="ts">
const word = "Qiita";
</script>

<template>
  <div class="title">{{ word }}</div>
</template>  

<style scoped>
.title{  color:lawngreen;
  font-size: 20px;
}
</style>
```

# v-bind
変数をHTMLタグの属性に値を渡す

```vue:NG
<script setup lang="ts">
const url = 'https://www.google.com/'
</script>

<template>
    <a href="url">LINK</a>
</template>
```

```vue:v-bind
<script setup lang="ts">
const url = 'https://www.google.com/'
</script>

<template>
    <a v-bind:href="url">LINK</a>
</template>
```

# v-on
クリックなどのイベント処理の関数を渡す

```vue:v-on
<script setup lang="ts">
const user = "Mike";
const hello = (user:string) => {
    alert('Hello ' + user + '!')
}
</script>

<template>
    <button v-on:click="hello(user)">HELLO</button>
</template>
```

# Ref / reactive
`リアクティブシステム`：Vue.jsの仕組み。データが変化した時、変化内容が即座にDOM(テンプレート)に反映される

```vue:NG
<script setup lang="ts">
let itemName = "Qiita";
const input = (event: any) => {
    // 変数が変わってもテンプレートは更新されない
    itemName = event.target.value;
}
</script>

<template>
    <input v-on:input="input"/>
    <label>{{ itemName }}</label> 
</template>
```

単一の値をリアクティブにするにはRefを使用

```vue:Ref
<script setup lang="ts">
import { ref } from 'vue'
const itemName = ref<string>('Qiita');
const input = (event: any) => {
    itemName1.value = event.target.value;
}
</script>

<template>
    <input v-on:input="input"/>
    <label>{{ itemName }}</label> 
</template>
```

オブジェクトをリアクティブにするにはreactive関数を使用

```vue:reactive
<script setup lang="ts">
import { reactive } from 'vue'
const item = reactive({
    name: 'Qiita'
})

const input = (event: any) => {
    item.name = event.target.value;
}
</script>

<template>
    <input v-on:input="input"/>
    <label>{{ item.name }}</label> 
</template>
```

# 双方向データバインディング v-model

inputフィールドが双方向にバインドする場合は、v-modelディレクティブを使用する
（Clearボタンでlabelのだけではなく、inputフィールドの値も削除する）

```vue:v-model
<script setup lang="ts">
import { reactive } from 'vue'
const item = reactive({
    name: 'Qiita'
})

const input = (event: any) => {
    item.name = event.target.value;
}

const clear = () => {
    item.name = ''
}
</script>

<template>
    <input v-model="item.name"/>
    <!-- valueでオブジェクトを参照した時と同じ処理になる -->
    <!-- <input v-on:input="input" v-bind:value="item.name"/> -->
    <button v-on:click="clear">Clear</button>
    <label>{{ item.name }}</label> 
</template>
```

# 算出プロパティ computed
条件を基に値を生成する場合、computedを使用する。
computedを使用することで、vue内でキャッシュ等最適化される。

これでも動くが、vueではテンプレート内にロジックを持たせないように記載する

```vue:NG
<template>
    <label>{{ item.name == "Jack" ? "It's Jack" : "Not Jack"}}</label>
</template>
```

```vue:computed
<script setup lang="ts">
import { computed } from 'vue'

const nameLabel = computed(() => {
    if (item.name == "Jack") {
        return "It's Jack";
    } else {
        return "Not Jack";
    }
})
</script>

<template>
    <label>{{ nameLabel }}</label>
</template>
```

# 監視プロパティ watch 

こちらでもcomputed同様の処理が可能。

```vue:watch
<script setup lang="ts">
const nameLabel = ref<string>(item.name)
// 要素をリアクティブな値で返す
const { name } = toRefs(item)

// 第一引数：watchしたいリアクティブな値
// 第二引数：値が変更された時の処理
watch(name, () => {
    if (name.value == "Jack") {
        nameLabel.value = "It's Jack";
    } else {
        nameLabel.value =  "Not Jack";
    }
})
</script>
```

# 備考：eventの中身を見る

```vue:event
<script setup lang="ts">
const input = (event: any) => {    
    console.log(event);
    console.log(event.target.value);
}
</script>

<template>
    <input v-on:input="input"/>
</template>
```

# 参考
https://www.udemy.com/course/vue3-typescript/