こんぶにのブログ

エンジニアという職業を通して学んだことを発信するブログです。

Vue.jsを学んでみた

公式チュートリアル

今回は公式のチュートリアルとドキュメントを使って色々学んでいく。

学んだこと

チュートリアル

//reactiveというのをこの後ろで使ってるから
import { reactive } from 'vue' 

//これはjavaxcriptのproxyというものを使用しているらしい。オブジェクトを直接作成しないで間接的にオブジェクトを作成できる
const counter = reactive({
  count: 0
})

console.log(counter.count) // 0
counter.count++

<template>
//この中にhtmlを書く
//上の部分で作成した変数を使いたい場合はこんな感じ。
<h1>{{ counter.count}}</h1>

</template>

v-bind

タグ内の属性に変数を使いたいって時はv-bind:属性 = 変数とする。
初めはマジで意味が分からなかった。
例えばこんなコードがあったとする。

<script setup>
import { ref } from 'vue'

const titleClass = ref('title')
</script>

<template>
  <h1 class="title">Make me red</h1> <!-- add dynamic class binding here -->
</template>

<style>
.title {
  color: red;
}
</style>

こんなコードを以下のように動的にできる。

<script setup>
import { ref } from 'vue'

const titleClass = ref('title')
</script>

<template>
  <h1 :class=titleClass>Make me red</h1> <!-- add dynamic class binding here -->
</template>

<style>
.title {
  color: red;
}
</style>

状況によってidだったり、nameだったり、classだったりの値を変えたいときに便利そう。
全く同じDOMなのに、属性値だけが違う時に便利そう。
これをv-bindと呼ぶ。良く使うので:だけでOK。

v-on

要はon~ 系のイベントを発火させるもの。

<setScript>

count = ref (0)
function plus() {
  count.value++
}

</script>

<template>
 // クリックしたらsetscriptで書いたfunction plusが発動する
  <button v-on:click="plus">
  //countの状態はリセットされずに保持して表示されるため、変数の中身もどんどん増えていく
  <p>{{ count }}</p>
</template>

v-model

v-bindとv-onを一緒に使いたいときはv-modelが使える
要は、input v-model=定数名としたとき、inputで記述した内容がそのまま定数.valueに代入されるって感じっぽい。

//こんなのがtemplateタグの中にあったとして、
<input :value="text" @input="onInput">

//上のをクリックするたびに、入力した値を取得して、定数textに代入して、templateに表示。
const text = ref('')
function onInput(e) {
  text.value = e.target.value
}

これは双方向に値を扱っていると言える。
template→setScript→templateと値を渡し合っているので、双方向。
こんな時は定数のtextの値を渡し合っているので、<input v-model="text" placeholder="Type here">
としてやる。
すると、不思議なことにたったこれだけで、定数textの中身を変更できるし、input入力したときにonInputも発動するし、ということが起きる。
おそらく、v-modelに記述した名前を取り扱っている部分から判断しているのだろうが・・・
しかし、いくつもの関数内で同じ定数を使っていたらどうなるのだろう?という疑問がわいた。

v-if

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>

awesomeの真偽によって、出力されるタグが変わる。
ここは問題なく理解。

v-for

ここはチュートリアルがめちゃくちゃ難しかった。 もはやv-for関係ないところで難しくするのやめてくれ。
v-for自体は簡単でいわゆるfor文。
v-forって書いたタグが繰り返される。
v-for="(word in List)"でListっていう名前の配列を、wordっていう名前で出力する。
あとは同じタグの中に、:key="word.id"みたいにすれば、keyも出力できるよ、というもの。
以上。
のはずなんだが、チュートリアルで追加ボタンと削除ボタンを完成させろというのがなかなかややこしかった。
今送られてきてるのは.value?.text?てかそもそもfilterってどんなだったっけ?アロー関数ってどんなんだっけ?
という基礎がぼろぼろなことが判明した。

v-forチュートリアルでつまづいたポイントまとめ。

・filterはArrayインスタンスのメソッド。Array.filter(条件)という感じ。
・filterの引数は関数。なので引数が変な感じになってる(個人的に)
・filter((listの中身のひとつずつの名前。勝手につけてOK)=>returnする値。ここで判定をしたりすれば最終的にtruefalseが返る)
・vueのrefの中で配列を作った場合、定数.valueの中に配列がある。 だからforで回すのは定数.value

算出プロパティー

意味が分からん。
全く意味が分からない。
computeメソッドをご紹介してくれたのだが、全く分からない。
なんでこれが必要なんだ?とか、別に他のやり方でもいけそうじゃない? とか思う。
とりあえず、computeってのはある条件に基づいて、常に定数の中身を計算して動的に変更できるものってことらしい。
どうも、このアロー関数形式が苦手だ。
短く書けることが便利でかっこいいというのは確かにそうだが、分かりにくくなってたら意味がない気がする。
何をしてて、何がどう返ってくるのかというのが直感的に分からない。
私はこいつが嫌いだ。
そしてようやくcomputedの仕様を理解し、正解っぽく書いたのだが全く動かない。
なんと、import { ref, computed } from 'vue'にcomputedを追加しないといけなかったのだ。
最悪だ。
こんくらい書いといてくれよ・・・。
こういうのあるからチュートリアルって嫌いなんだよな。

ライフサイクルとテンプレート参照

ここで出てくるのがマウント。
当たり前のようにマウントって言ってくるけど、何?って感じ。
vueで作るインスタンスと、htmlのdomを結び付けること、らしい。
そういわれると、ああそういうことね、ってわかる。
onMountedってのを使えって言われるんだけど、これがなんなのかってのを自分なりに理解した。
setScriptで定義したtest=ref('')ってのがあったとして、templateタグの中に<p ref="test">てすと</p>ってのを作ったとする。
ただ、setScript時点ではtemplateタグの中身はまだ描画(レンダー)されていない。なので、結び付け(マウント)が出来ない。
だから、マウントされたあと(描画されて結び付けられた後)に、こういう処理をしてよ、という指示をonMountedに書くのだろう。
うーん、自分で説明してもだいぶ分かりにくいな。
フロントエンジニアってすげえ。

ウォッチャー

こいつは簡単。
定義した値の中身に変化があったとき、何かをしてくれる。

コンポーネント

こいつも簡単。
別ファイルをimportで読み込んで、template内にて、<ファイル名 />とする。
そうすると別ファイルのtemplateが描画される。

props

コンストラクタ的なイメージ。
importした別ファイルに値を送れる。

イベントの発行

ちょっと分かりにくかったが、なんとなく理解。
コンポーネントでこうする。

// ChildCompという名前でimportしたファイルを読み込んだとき、responseというイベントを発火させます
// その引数はmsgという名前で、最終的にはchildMsgという変数にmsgを入れてくれます。
<ChildComp @response="(msg) => childMsg = msg" />

コンポーネントの方でこう。

多分、お約束。こう書くよ、ってだけの話。  
こういう名前で、イベントを定義するよ~
const emit = defineEmits(['response','test'])

このイベントを発行(実行)するよ~。引数はhello from childだよ~
emit('response', 'hello from child')

コンポーネントないで子コンポーネントを読み込んだ時、responseという子の中で定義したイベントを発行している。
どういう時に使うんだろう。

slot

公式ドキュメントの説明が分かりやすかった。
スロット | Vue.js
ある決まったボタンの構造とかがあって、画面によってメッセージだけが違うとかなら、使いまわせるようになる。
親から子のタグの方にメッセージを送って、子の方ではslotと書き込んだ箇所に受け取ったメッセージが入る。以上。