Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

vue.js02

Last updated at Posted at 2024-05-01

テンプレート構文について

スクリーンショット 2024-05-01 215716.png

  • このHTMLはそのままブラウザにHTMLとして渡されるわけではない
  • 「.vue」の中身はViteなどによってJavascriptのコードに変換される
  • HTMLのコードをjavascriptに変換してくれている
  • テンプレート構文がHTMLのルールに従ってくれている

二重波括弧でデータを描画

<script setup></script>
<template>
  <div>{{ 3 + 4 }}</div>
</template>

スクリーンショット 2024-05-01 224142.png

  • 二重波括弧の中にはjavascriptの式を書くことができる
  • 二重波括弧の中に「3+4」と書くと画面には「7」が表示される

scriptの中で定義した定数、関数も使える

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

const count = ref(2)
</script>
<template>
  <div>{{ count + 3 }}</div>
</template>

スクリーンショット 2024-05-01 224736.png

  • 定義した定数countの値も反映される
<script setup>
import { ref } from 'vue'

const count = ref(2)
</script>
<template>
  <div>{{ count > 3 ? 'Yes' : 'No' }}</div>
</template>

スクリーンショット 2024-05-01 225133.png

  • 三項演算子も書ける

【注意点】

二重波括弧の中には単一の式だけ書ける

  • 1つの式だけ書ける
  • if文は書けない

二重波括弧内でscriptで定義された定数、関数などを使う場合は、そのデータがscript内でトップレベルで定義されている必要がある

  • トップレベルとは?
    →if文の中、関数の中などに入っていない、ということ
  • if文の中、関数の中で定義された関数はtemplateでは使えない

ディレクティブについて

htmlディレクティブ

<script setup>
import { ref } from 'vue'
const message = ref('<h1>Hello</h1>')
</script>
<template>
  <div>{{ message }}</div>
</template>

スクリーンショット 2024-05-05 163935.png

  • これはHelloがタグ含めて文字列として表示されてしまう
<script setup>
import { ref } from 'vue'
const message = ref('<h1>Hello</h1>')
</script>
<template>
  <div v-html="message"></div>
</template>

スクリーンショット 2024-05-05 164132.png

  • <div v-html="message"></div>とすることでタグが反映される!
  • 便利だがセキュリティ上の問題があったりする
  • ユーザーからもらった値ではない信頼できるデータのみ使用する必要がある
  • ウェブページが自由に書き換えられてしまうため

v-bindディレクティブ

<script setup>
import { ref } from 'vue'
const vueURL = ref('https://vuejs.org')
</script>
<template>
  <a href="{{ vueURL }}">Vue.js</a>
</template>

スクリーンショット 2024-05-05 164922.png

  • このURL指定方法だとリンクできない。押しても飛ばない。
  • 二重波括弧は属性の値では使用できない
<script setup>
import { ref } from 'vue'
const vueURL = ref('https://vuejs.org')
</script>
<template>
  <a v-bind:href="vueURL">Vue.js</a>
</template>
  • <a v-bind:href="vueURL">Vue.js</a>
  • こうするとリンクが設定できる
href属性に限った話ではない!
<script setup>
import { ref } from 'vue'
const vueURL = ref('https://vuejs.org')
const vueId = ref('vue-link')
</script>
<template>
  <a v-bind:id="vueId" v-bind:href="vueURL">Vue.js</a>
</template>

スクリーンショット 2024-05-05 165454.png

  • idにも動的に値を設定できる
  • どうな属性にもv-bindで値を設定できる
  • 普通の値には二重波括弧を使う、属性値にはv-bindを使う
  • v-bindディレクティブを非常に頻繁に利用される

v-bindは省略記法あり

<a :id="vueId" :href="vueURL">Vue.js</a>
  • :のみで記述できる(v-bindは省ける)
  • eslintの設定では省略記法が推奨されており、保存するだけで省略される(されなかったけど)

属性名と属性値の変数や定数が同じ名前の場合は「=以降」を省略して書くこともできる

<script setup>
import { ref } from 'vue'
const id = ref('vue-link')
</script>
<template>
  <a :id>Vue.js</a>
</template>
  • <a :id>Vue.js</a>
  • <a :id="id">Vue.js</a>
  • こちらが同じ状態ということ!
  • 属性名→「id」、属性名の定数→「id」の状態

undefinedとnullを入れるとその属性が存在しなくなる

<script setup>
import { ref } from 'vue'
const vueURL = ref('https://vuejs.org')
const vueId = ref('vue-link')
</script>
<template>
  <a :id="undefined" :href="null">Vue.js</a>
</template>

スクリーンショット 2024-05-05 171138.png

  • idもhrefも消えている状態

Boolean属性について

  • undefined、null以外にも「false」と入れるとその属性が消えるような属性もある
  • どんな属性なのか?
    →Boolean属性
Boolean属性とは
  • HTMLの話
  • 値をとらなくてもいい属性
<buttom disabled>ボタン</button>
  • ボタンタグにおけるdisabled属性など
Boolean属性に対してv-bindを使った場合、、
<buttom :disabled="null">ボタン</button>
<buttom :disabled="undefined">ボタン</button>
  • nullやundefinedを指定した時には消える
<buttom :disabled="false">ボタン</button>
  • falseを指定した時も消える
  • 「0」「-0」「0n」「NaN」を入れても消える
  • vue.jsが対応しているBoolean属性の一覧がある

v-bindで一度に複数の属性を指定する方法

<script setup>
import { ref } from 'vue'
const vueURL = ref('https://vuejs.org')
const vueId = ref('vue-link')
</script>
<template>
  <a :id="vueId" :href="vueURL">Vue.js</a>
</template>
  • それぞれに属性を指定している状態
<script setup>
import { ref } from 'vue'
const vueURL = ref('https://vuejs.org')
const vueId = ref('vue-link')
</script>
<template>
  <a v-bind="{ id: vueId, href: vueURL }">Vue.js</a>
</template>
  • このように書くとひとまとめにすることができる!

v-onディレクティブ

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <button v-on:click="count++">button</button>
</template>

スクリーンショット 2024-05-05 180644.png
スクリーンショット 2024-05-05 180650.png

  • v-onの中にcount++という処理を記述する
  • clickイベント発生のたびにcount++の処理が動く
  • ボタンを押すと数字が1つずつ増える
v-onも省略できる
<button @click="count++">button</button>
  • v-on:click@clickに省略できる
  • こちらも省略が推奨されている
関数の指定でも実行できる
<script setup>
import { ref } from 'vue'
const count = ref(0)
function countUp() {
  count.value++
}
</script>
<template>
  <p>{{ count }}</p>
  <button @click="countUp">button</button>
</template>
  • @clickに直接処理を書くのではなく、関数を指定する形

  • こちらでも同様の処理ができる

  • clickなどの実行→イベント

  • イベントの中身→ハンドラ

  • vue.jsには処理を直接各パターン、関数を書くパターンの2つのパターンのハンドラがある

  • 直接書くハンドラ→インラインハンドラ

  • 関数を書くハンドラ→メソッドハンドラ

clickイベント以外にどんなイベントを指定できる?
  • ドキュメントに書かれている
  • いっぱいある

イベントオブジェクト

  • イベントオブジェクトの取得方法
  • clickイベントのようなブラウザが発生させているイベントはそのイベントが発生した時に、同時にイベントオブジェクトというそのイベントの情報を持ったオブジェクトを生成している
  • vue.jsはそれを取得できるようになっている
function countUp(event) {
  console.log(event)
  count.value++
}

スクリーンショット 2024-05-05 182924.png

  • 第一引数に指定するだけで、ボタンをクリックするとオブジェクトが表示される
  • イベントの情報を持ったイベントオブジェクト
  • 例えばclientX、clienYはボタンがクリックされた時のマウスの縦軸・横軸のポジション
<script setup>
import { ref } from 'vue'
const count = ref(0)
function countUp(event) {
  count.value = event.clientX
}
</script>
<template>
  <p>{{ count }}</p>
  <button @click="countUp">button</button>
</template>

スクリーンショット 2024-05-05 183254.png

  • こうするとボタンを押した時のマウスの位置を表示することができる
インラインハンドラ(直接書くハンドラ)はどのようにイベントオブジェクトにアクセスするのか
<script setup>
import { ref } from 'vue'
const count = ref(0)
function countUp(event) {
  count.value = event.clientX
}
</script>
<template>
  <p>{{ count }}</p>
  <button @click="count = $event.clientX">button</button>
</template>
  • インラインハンドラでは$eventという特殊な変数を使うことができる
  • 4eventにイベントオブジェクトが格納されている
  • 上記で同じような動きが実装できる

v-onでハンドラに引数を渡す

  • メソッドハンドラとして設定した関数に引数を渡したい場合
  • メソッドハンドラとして呼び出すのではなく、インラインハンドラとして関数呼び出し式を記述する
<script setup>
import { ref } from 'vue'
const count = ref(0)
function countUp(event, times) {
  count.value = event.clientX * times
}
</script>
<template>
  <p>{{ count }}</p>
  <button @click="countUp($event, 5)">button</button>
</template>
  • <button @click="countUp($event, 5)">button</button>
  • このようにインラインハンドラとして記述する($eventを利用すること)
  • スクリーンショット 2024-05-05 184328.png
  • クリック位置×5の数値を表示している

イベント修飾子

preventDefalult

  • デフォルトの挙動を防ぐ
<script setup>
import { ref } from 'vue'
const count = ref(0)
function countUp(event, times) {
  count.value = event.clientX * times
}
</script>
<template>
  <a href="https://vuejs.org" @click="$event.preventDefault()">Vue.js</a>
</template>

スクリーンショット 2024-05-05 212934.png

  • クリックしてもデフォルトの挙動が動かなくされているのでリンクしない

stopPropagation

  • 伝播を止める
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <div @click="count++">
    <button>button</button>
  </div>
</template>

スクリーンショット 2024-05-05 213520.png

  • これはボタン押すと通常通り数字増える
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <div @click="count++">
    <button @click="$event.stopPropagation()">button</button>
  </div>
</template>

スクリーンショット 2024-05-05 213700.png

  • これは増えない、ボタンが動作しなくなる
  • 親の要素にクリックイベントが発生したことを伝えない(伝播させない)という処理になっている

vue.jsではpreventDefaultとstopPropagationをよく使うので、簡単に実行できるシステムを持っている

→これがイベント修飾子

prevent

<script setup>
import { ref } from 'vue'
const count = ref(0)
function countUp(event, times) {
  count.value = event.clientX * times
}
</script>
<template>
  <a href="https://vuejs.org" @click="$event.preventDefault()">Vue.js</a>
</template>

↓↓↓↓

<script setup>
import { ref } from 'vue'
const count = ref(0)
function countUp(event, times) {
  count.value = event.clientX * times
}
</script>
<template>
  <a href="https://vuejs.org" @click.prevent="">Vue.js</a>
</template>
  • <a href="https://vuejs.org" @click="$event.preventDefault()">Vue.js</a>
  • <a href="https://vuejs.org" @click.prevent="">Vue.js</a>
  • このように書き換えるだけで同じ記述になる
  • <a href="https://vuejs.org" @click.prevent>Vue.js</a>
  • ↑これでも問題なし

stop

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <div @click="count++">
    <button @click="$event.stopPropagation()">button</button>
  </div>
</template>

↓↓↓↓

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <div @click="count++">
    <button @click="$event.stop="">button</button>
  </div>
</template>
  • <button @click="$event.stopPropagation()">button</button>
  • <button @click="$event.stop="">button</button>
  • このように書き換えるだけで同じ記述になる
  • <button @click="$event.stop>button</button>
  • ↑これでも問題なし

stopや、preventを実行した上でなにか処理を追加することもできる

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <div @click="count++">
    <button @click="$event.stop="count = 30">button</button>
  </div>
</template>

スクリーンショット 2024-05-05 215436.png

  • 追加でインラインハンドラ、イベントハンドラを追加することもできる
  • ボタンを押すと30に数値が変更する(カウントアップの処理は動かないまま)

両方使うこともできる

  • <a href="https://vuejs.org" @click.prevent.stop>Vue.js</a>
  • 両方も使える

キー修飾子

  • イベント修飾子に似たもの、キーボード系のイベントのみに使える
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <input type="text" @keyup="count++" />
</template>

スクリーンショット 2024-05-06 005505.png

  • keyup
  • ↑キーボードを押して離した時に発生するイベント
  • 文字を入力するとカウントが増える

すべてのキーボードではなく、特定のキーボードのみに反映させたい

キー修飾子

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <input type="text" @keyup.space="count++" />
</template>

スクリーンショット 2024-05-06 005903.png

  • @keyup.space="count++"とするとスペースを押した時だけカウントが反映される
複数組み合わせも可能
vue.js
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
  <p>{{ count }}</p>
  <input type="text" @keyup.space.delete="count++" />
</template>

スクリーンショット 2024-05-06 010053.png

  • <input type="text" @keyup.space.delete="count++" />
  • スペースを押した時と、デリートを押した時に反映される状態

ディレクティブの構造

スクリーンショット 2024-05-06 010336.png

  • 角括弧を使ってディレクティブの引数にscriptのデータを指定できる
  • 解説見たがよくわからなかった

v-model

<script setup>
import { ref } from 'vue'
const userInput = ref('')
</script>
<template>
  <p>{{ userInput }}</p>
  <input v-model="userInput" type="text" />
</template>

スクリーンショット 2024-05-06 011604.png

  • inputタグのようにユーザーから入力されたデータはスクリプトタグの中でも使いたい
  • スクリプトのデータと入力欄を常に同じ値にする
    →そのような時に利用するのがv-model
  • v-modelを設定するだけで、inputタグとconst userInput = ref('')の値は常に同じ値になる
<script setup>
import { ref } from 'vue'
const userInput = ref('')
</script>
<template>
  <p>{{ userInput }}</p>
  <input v-model="userInput" type="text" />
  <button @click="userInput = 'hi'">button</button>
</template>

スクリーンショット 2024-05-06 012039.png
スクリーンショット 2024-05-06 012044.png

  • ボタン押すとどちらも「hi」に変わる

computed

  • リアクティブシステムを守ったまま、処理を1つにまとめる方法
<script setup>
import { ref } from 'vue'
const score = ref(0)
</script>
<template>
  <p>{{ score > 3 ? 'Good' : 'Bad' }}</p>
  <p>{{ score }}</p>
  <button @click="score++">+1</button>
</template>

スクリーンショット 2024-05-06 125858.png
スクリーンショット 2024-05-06 125905.png

  • ボタンを押すと数値が増えて、判定によってBAd、Goodを表示する処理を作った
<script setup>
import { ref } from 'vue'
const score = ref(0)
const evaluation = score.value > 3 ? 'Good' : 'Bad'
</script>
<template>
  <p>{{ evaluation }}</p>
  <p>{{ score }}</p>
  <button @click="score++">+1</button>
</template>
  • これは上のものと同じ式なのか→違う!
  • <p>{{ score > 3 ? 'Good' : 'Bad' }}</p>
  • {{ evaluation }}

  • この2つは同じ処理なのか→違う!
  • const evaluation = score.value > 3 ? 'Good' : 'Bad'
  • ここのevaluationに入る値は何なのか?
  • score.value > 3 ? 'Good' : 'Bad'この式が評価された値が入る
  • この式が評価された値とは?
  • const score = ref(0)→つまり0が入る
  • つまりBadが常にconst evaluationに入る状態
    スクリーンショット 2024-05-06 130721.png
  • なので数値を増やしてもずっとBadが表示
<script setup>
import { ref } from 'vue'
const score = ref(0)
const evaluation = ref(score.value > 3 ? 'Good' : 'Bad')
</script>
<template>
  <p>{{ evaluation }}</p>
  <p>{{ score }}</p>
  <button @click="score++">+1</button>
</template>
  • const evaluation = ref(score.value > 3 ? 'Good' : 'Bad')
  • ここをrefで包めばいいのでは?→違う
  • refの関数の中にBadという文字列を入れているだけなので同じ
    スクリーンショット 2024-05-06 130721.png

↑説明の意味はさっぱりわからないがとにかく無理だということ

リアクティブシステムを保ったまま式をまとめたい(上記はまとめられていない状態ということ)

その時に使用するのがcomputed

  • import { ref, computed } from 'vue'
  • refやリアクティブと同様にインポートして使用する
const evaluation = computed(() => {
  score.value > 3 ? 'Good' : 'Bad'
})
  • refやリアクティブと同様に関数として呼び出す
  • computedは引数に関数を入れる必要がある
  • 関数の中でまとめたい処理を記述する
const evaluation = computed(() => {
  score.value > 3 ? 'Good' : 'Bad'
})
console.log(evaluation)

スクリーンショット 2024-05-06 131833.png

  • console.logでevaluationの中身を見てみる
  • refオブジェクトのように複雑なオブジェクトを返している
  • ほとんどrefオブジェクトと同じ(computed refオブジェクトと呼ぶ)
  • スクリプトやテンプレートでまるでrefオブジェクトのように使用できる
console.log(evaluation.value)
  • このようにもできる
  • こうするとなにが返ってくるのか?
  • .valueに最初にアクセスした時に、computedに渡した引数が実行される 
    その返り値が.valueの中に格納される
const evaluation = computed(() => {
  return score.value > 3 ? 'Good' : 'Bad'
})
console.log(evaluation.value)

スクリーンショット 2024-05-06 132449.png

  • 返り値が無かったのでいったんreturnで返してあげると、Badが表示される
  • computedの関数の中では必ずreturnをする必要がある
  • returnが無いとeslintの設定でエラーも出る

スクリーンショット 2024-05-06 132702.png
スクリーンショット 2024-05-06 132707.png

  • computedが内部的に色んな処理を実行しているので、ボタンを押すとBadがGoodに変化するようになっている
  • computedを使って引数に関数を入れてreturnでまとめた処理を返せばいい感じに処理を一つにまとめることができる
  • 処理をひとつにまとめる、の意味がいまいちよくわからない
  • computedの内部処理の解説も意味がわからなかった

computedを使う時はここに注意する

  • いったん割愛
  • 後にまとめる
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?