changed 4 years ago
Published Linked with GitHub

Vueハンズオンの前の基礎の基礎

in Kamakura MokMok Hack

@tyshgc

slide: https://hackmd.io/@tyshgc/kamakura-mokmok-vue-react-handson/


Vue.js?


Vue.jsはWebフロントエンドの
フレームワークの一つ


簡単に言うと…

データの表示入力
うまいことやってくれるもの


Vueの基本のキ


Webアプリケーションなので
HTMLの所定のDOM内にアプリケーションを
構築していきます。

<div id="app"> <!-- ここにアプリを構築する --> </div>

Vueインスタンスを作成

new Vue({ el: "#app", //HTMLのどこに表示するか data() { // メッセージのデータ return { message: "御用でしょうか?" }; }, methods: { // 入力処理 onCancel() { this.message = "かしこまりー!!"; } }, template: ` <div> <p>{{message}}</p> <button @click="onCancel">用はない</button> </div> ` });


しかし…

templateにアプリケーションの構造を全部書くのはツライ…

template: ` <div> <p>{{message}}</p> <button @click="onCancel">用はない</button> </div> `

コンポーネントを使おう!


コンポーネントとは?

👉アプリを構成する部品


🧩御用聞きのメッセージ

<p>{{message}}</p>

🧩返事をするボタン

<button @click="onCancel">用はない</button>

それぞれ部品 = コンポーネントとして扱えばいい


🧩御用聞きのメッセージ Servant.vue を作成

<template> <p>{{message}}</p> </template> <script> export default { name: "Servant", // コンポーネント名 props: { // このコンポーネントに渡すことが可能な値 message: String } } </script>

Vueインスタンスにコンポーネントを登録する

import Servant from "./Servant.vue" new Vue({ el: "#app", //HTMLのどこに表示するか //...<同じなので省略>... components: { //コンポーネントを登録 Servant }, template: ` <div> <servant :message="message" /> <button @click="onCancel">用はないよ</button> </div> ` });

🧩キャンセルボタン CancelButton.vue を作成

<template> <button @click="onCommand">用はないよ</button> </template> <script> export default { name: "CancelButton", methods: { onCommand() { // $emitで呼び出し元のイベントを登録して // ここで発火できる this.$emit("do-command"); } } }; </script>

Vueインスタンスにコンポーネントを登録する

//...<同じなので省略>... import CancelButton from "./CancelButton.vue" new Vue({ el: "#app", //HTMLのどこに表示するか //...<同じなので省略>... components: { //コンポーネントを登録 Servant, CancelButton }, template: ` <div> <servant :message="message" /> <cancel-button @do-command="onCancel" /> </div> ` });


御用聞きが文章だけだと寂しい…

絵文字で工夫してみましょう!


御用聞きのシーンごとに
絵文字をコンポーネントにする

|シーン|絵文字|
|-|-|-|
|用件をたずねる時|💁‍♀️|
|承知した時|🙆‍♀️|


Emoji.vue

<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 値の真偽を見て条件を満たした場合DOMを表示
v-else ifの条件を満たさなかった場合にDOMを表示
v-else-if 別の条件の場合
v-for 繰り返し

詳しくは公式ドキュメントを読もう

Vue 2.0 ドキュメント - ディレクティブ


御用聞きのメッセージに絵文字を
差し込めるようにします。

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> ` });

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

コンポーネントを入れ子にすると…

<servant><Component></servant>

このままではエラーになる


Servant.vueをこうする

<template> <p> <slot /> <span>{{message}}</span> </p> </template>

ここまでで気になる点

  • 用件たずねているか否かをisAskで現したプロパティが適していないのでは?
  • 正確には「用件をたずねる」「了解をする」というモードであるべき
  • アプリケーション内では御用聞き〈Servant〉のモードを表現した方がわかりやすい

Pure JavascriptではEnum使えないので…
ぽいものをつくってみる

export const SERVANT_MODE = { ASK: Symbol(), OK: Symbol() };

それを踏まえてなやんかんやいじって…



ReactとVueの違いは?

  • ReactはViewライブラリ
  • ざっくり言うとコンポーネントの考え方は基本的に同じ
  • Reactのコンポーネントにもpropsで値が渡せる
  • VueのdataがReactのstateと理解すれば良い(正確には仕組みが違うけど…)
  • Vueは子から親へのデータ参照やイベント発火が可能
  • Reactは親から子への一方向(イベントもpropsで渡す)

状態管理を扱う

状態(=State)を一箇所に集中させて管理


メリット

  • 複数のインスタンスやコンポーネント間でStateを共有できる
  • アプリケーションが大きくなると表示・状態・入力など役割を分けた方が扱いやすい

デメリット

  • インスタンスが一つ、扱うアプリケーションが小さい場合は冗長的になる
  • コンポーネントのどこでも同じ状態を扱えるので書き方次第で変更範囲が広くなりバグの温床に…

さっきのコードをVuexにしてみる

この規模だと逆に冗長的になので本当は使わない



Reactの場合は?

  • Reactの場合はReduxで状態管理できる。ただしこちらはもっと冗長的。
  • そのほかにMobxやUnduxなどある。
  • MobXが比較的Vuexと似ている。

ハンズオンする


つくるもの

簡単なストップウォッチアプリを作ります。
基礎の基礎のさらにつっこんだ基礎の部分や状態管理Vuexまでできればがんばりましょう!


リポジトリ

https://github.com/kamakura-mok-mok-hack/vue-handson-stopwatch

Select a repo