<!-- .slide: data-background="#020202" -->
### Vueハンズオンの前の基礎の基礎
in [Kamakura MokMok Hack](https://kamkura-mokmok.connpass.com/)
[@tyshgc](https://twitter.com/tyshgc)
<!-- Put the link to this slide here so people can follow -->
<span style="font-size: 0.3em;">slide: https://hackmd.io/@tyshgc/kamakura-mokmok-vue-react-handson/</span>
---
Vue.js?
---
Vue.jsはWebフロントエンドの<br />フレームワークの一つ
---
簡単に言うと…
<span style="font-size: 0.8em;">データの<strong style="color:#cc3300;">表示</strong>と<strong style="color:#cc3300;">入力</strong>を<br />うまいことやってくれるもの</span>
---
### Vueの基本のキ
---
<p style="font-size:0.8em;">Webアプリケーションなので<br />HTMLの所定のDOM内にアプリケーションを<br />構築していきます。</p>
```html=
<div id="app">
<!-- ここにアプリを構築する -->
</div>
```
---
<p style="font-size:0.8em;">Vueインスタンスを作成</p>
```javascript=
new Vue({
el: "#app", //HTMLのどこに表示するか
data() { // メッセージのデータ
return {
message: "御用でしょうか?"
};
},
methods: { // 入力処理
onCancel() {
this.message = "かしこまりー!!";
}
},
template: `
<div>
<p>{{message}}</p>
<button @click="onCancel">用はない</button>
</div>
`
});
```
---
<iframe src="https://codesandbox.io/embed/vuenoshuomingyongsono1-i3pm1?fontsize=14" title="Vueの説明用その1" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
---
しかし…
<span style="font-size: 0.8em;">templateにアプリケーションの構造を全部書くのはツライ…</span>
```javascript=
template: `
<div>
<p>{{message}}</p>
<button @click="onCancel">用はない</button>
</div>
`
```
---
## コンポーネントを使おう!
---
コンポーネントとは?
<span style="font-size: 0.8em;">👉アプリを構成する部品</span>
---
🧩御用聞きのメッセージ
```html=
<p>{{message}}</p>
```
🧩返事をするボタン
```html=
<button @click="onCancel">用はない</button>
```
---
それぞれ部品 = コンポーネントとして扱えばいい
---
🧩御用聞きのメッセージ Servant.vue を作成
```javascript=
<template>
<p>{{message}}</p>
</template>
<script>
export default {
name: "Servant", // コンポーネント名
props: {
// このコンポーネントに渡すことが可能な値
message: String
}
}
</script>
```
---
Vueインスタンスにコンポーネントを登録する
```javascript=
import Servant from "./Servant.vue"
new Vue({
el: "#app", //HTMLのどこに表示するか
//...<同じなので省略>...
components: { //コンポーネントを登録
Servant
},
template: `
<div>
<servant :message="message" />
<button @click="onCancel">用はないよ</button>
</div>
`
});
```
---
🧩キャンセルボタン CancelButton.vue を作成
```javascript=
<template>
<button @click="onCommand">用はないよ</button>
</template>
<script>
export default {
name: "CancelButton",
methods: {
onCommand() {
// $emitで呼び出し元のイベントを登録して
// ここで発火できる
this.$emit("do-command");
}
}
};
</script>
```
---
Vueインスタンスにコンポーネントを登録する
```javascript=
//...<同じなので省略>...
import CancelButton from "./CancelButton.vue"
new Vue({
el: "#app", //HTMLのどこに表示するか
//...<同じなので省略>...
components: { //コンポーネントを登録
Servant,
CancelButton
},
template: `
<div>
<servant :message="message" />
<cancel-button @do-command="onCancel" />
</div>
`
});
```
---
<iframe src="https://codesandbox.io/embed/vuenoshuomingyongsono2-uubof?fontsize=14" title="Vueの説明用その2" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
---
御用聞きが文章だけだと寂しい…<br />
絵文字で工夫してみましょう!
---
御用聞きのシーンごとに<br />絵文字をコンポーネントにする
|シーン|絵文字|
|---|---|---|
|用件をたずねる時|💁♀️|
|承知した時|🙆♀️|
---
Emoji.vue
```javascript=
<template>
<i v-if="isAsk">💁♀️</i>
<i v-else>🙆♀️</i>
</template>
<script>
export default {
name: "Ask",
props: {
isAsk: Boolean,
isOk: Boolean
}
};
</script>
```
---
### Point 🌟
|ディレクティブ|役割|
|---|---|
|v-if|<span style="font-size: 0.5em;">値の真偽を見て条件を満たした場合DOMを表示</span>|
|v-else|<span style="font-size: 0.5em;">ifの条件を満たさなかった場合にDOMを表示</span>|
|v-else-if|<span style="font-size: 0.5em;">別の条件の場合</span>|
|v-for|<span style="font-size: 0.5em;">繰り返し</span>|
---
詳しくは公式ドキュメントを読もう
[Vue 2.0 ドキュメント - ディレクティブ](https://jp.vuejs.org/v2/api/#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96)
---
御用聞きのメッセージに絵文字を<br />差し込めるようにします。
```javascript=
new Vue({
el: "#app", //HTMLのどこに表示するか
data() {
return {
message: "御用でしょうか?",
isAsk: true //用件をたずねているか?
};
},
methods: { // 入力処理
onCancel() {
this.message = "かしこまりー!!";
this.isAsk = false;
}
},
components: { //コンポーネントを登録
//...<同じなので省略>...
Emoji,
},
template: `
<div>
<servant :message="message">
<emoji :is-ask="isAsk" />
</servant>
<cancel-button @do-command="onCancel" />
</div>
`
});
```
---
:exclamation:
コンポーネントを入れ子にすると…
```html=
<servant><Component></servant>
```
このままではエラーになる
---
Servant.vueをこうする
```javascript=
<template>
<p>
<slot />
<span>{{message}}</span>
</p>
</template>
```
---
### ここまでで気になる点
- <span style="font-size: 0.5em;">用件たずねているか否かをisAskで現したプロパティが適していないのでは?</span>
- <span style="font-size: 0.5em;">正確には「用件をたずねる」「了解をする」というモードであるべき</span>
- <span style="font-size: 0.5em;">アプリケーション内では御用聞き〈Servant〉のモードを表現した方がわかりやすい</span>
---
Pure JavascriptではEnum使えないので…
ぽいものをつくってみる
```javascript=
export const SERVANT_MODE = {
ASK: Symbol(),
OK: Symbol()
};
```
それを踏まえてなやんかんやいじって…
---
<iframe src="https://codesandbox.io/embed/vuenoshuomingyongsono3-fi4t5?fontsize=14" title="Vueの説明用その4" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
---
### ReactとVueの違いは?
- <span style="font-size: 0.5em;">ReactはViewライブラリ</span>
- <span style="font-size: 0.5em;">ざっくり言うとコンポーネントの考え方は基本的に同じ</span>
- <span style="font-size: 0.5em;">Reactのコンポーネントにもpropsで値が渡せる</span>
- <span style="font-size: 0.5em;">VueのdataがReactのstateと理解すれば良い(正確には仕組みが違うけど…)</span>
- <span style="font-size: 0.5em;">Vueは子から親へのデータ参照やイベント発火が可能</span>
- <span style="font-size: 0.5em;">Reactは親から子への一方向(イベントもpropsで渡す)</span>
---
### 状態管理を扱う
==状態(=State)を一箇所に集中させて管理==
---
### メリット
- <span style="font-size: 0.5em;">複数のインスタンスやコンポーネント間でStateを共有できる</span>
- <span style="font-size: 0.5em;">アプリケーションが大きくなると表示・状態・入力など役割を分けた方が扱いやすい</span>
---
### デメリット
- <span style="font-size: 0.5em;">インスタンスが一つ、扱うアプリケーションが小さい場合は冗長的になる</span>
- <span style="font-size: 0.5em;">コンポーネントのどこでも同じ状態を扱えるので書き方次第で変更範囲が広くなりバグの温床に…</span>
---
さっきのコードをVuexにしてみる
<span style="font-size: 0.5em;">この規模だと逆に冗長的になので本当は使わない</span>
---
<iframe src="https://codesandbox.io/embed/vuenoshuomingyongsono5-r4ntk?fontsize=14" title="Vueの説明用その5" allow="geolocation; microphone; camera; midi; vr; accelerometer; gyroscope; payment; ambient-light-sensor; encrypted-media; usb" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" sandbox="allow-modals allow-forms allow-popups allow-scripts allow-same-origin"></iframe>
---
### Reactの場合は?
- <span style="font-size: 0.5em;">Reactの場合はReduxで状態管理できる。ただしこちらはもっと冗長的。</span>
- <span style="font-size: 0.5em;">そのほかにMobxやUnduxなどある。</span>
- MobXが比較的Vuexと似ている。
---
## ハンズオンする
---
### つくるもの
簡単なストップウォッチアプリを作ります。
基礎の基礎のさらにつっこんだ基礎の部分や状態管理Vuexまでできればがんばりましょう!
---
### リポジトリ
https://github.com/kamakura-mok-mok-hack/vue-handson-stopwatch
{"metaMigratedAt":"2023-06-14T23:52:19.997Z","metaMigratedFrom":"YAML","title":"Vueハンズオンの前の基礎の基礎@Kamakura MokMok Hack","breaks":"true","description":"View the slide with \"Slide Mode\".","contributors":"[{\"id\":\"7146b451-0159-49a3-8efa-a31977017fda\",\"add\":10436,\"del\":2546}]"}