0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Vue3・Nuxt4の前にJavaScriptの基本を整理してみる

0
Posted at

JavaScriptの基本を、Vue3・Nuxt4で使うことを前提に整理してみます。
Vue3では画面の表示を変えるための値や関数を書き、Nuxt4ではそれをページやcomposableへ広げていくことになりそうです。その前に、JavaScriptの「値・データ・関数・クラス」を自分なりにまとめておきたくなりました。

今回は、画像解析結果の一覧や検索画面を作る場面をイメージしながら、JavaScriptの基礎を確認します。

まだ途中段階なので、勘違いなどあれば教えていただけるとうれしいです。

今日やったこと

JavaScriptの値、配列、オブジェクト、関数、クラスを整理し、Vue3・Nuxt4でどこまで優先して使いそうかを考えました。

JavaScriptは、画面へ値を表示する、入力を受け取る、ボタンを押したときに処理する、データを取得する、といった画面の動きを作るための言語です。画像解析結果を扱う画面で考えると、解析結果の一覧を持つ、検索語で絞り込む、詳細を選ぶ、といったところで使えそうです。

image.avif 「JavaScriptは書き方が多そうだけど、まずは画面を動かすために必要なところから覚えたい。」

Vue3では、refでリアクティブな値を作り、computedで別の値に基づく表示用の値を作れます。Nuxt4のapp/composables/では、再利用したいVueの処理をまとめられるようです。(Vue.js公式:リアクティブの基礎) (Nuxt4公式:composables) vueframework

JavaScriptの基本

まずは、JavaScriptだけでも出てくる値と変数を確認しました。

値の種類

JavaScriptでは、文字・数値・真偽値などを扱います。

// 文字列。画像名や検索語、画面に出すメッセージなどに使えそう
const imageName = '画像001'

// 数値。ID、検出件数、スコアなどに使えそう
const detectionCount = 3

// 真偽値。true は「はい」、false は「いいえ」と考える
const isLoading = false

// null は「意図的に値がない」状態を表すときに使う
const selectedResult = null

// undefined は、まだ値が入っていない場合などで出会いそう
let errorMessage

console.log(imageName, detectionCount, isLoading, selectedResult, errorMessage)
  • string:文字列。画像名、検索語、判定メッセージなど
  • number:数値。ID、検出件数、スコアなど
  • booleantrueまたはfalse。読み込み中か、詳細を開いているかなど
  • null:意図して値がない状態。選択中の結果がない場合など
  • undefined:値が未定義の状態

constlet

変数は、値へ名前を付けて扱うためのものです。

// const は、変数そのものを別の値へ再代入しない場合に使う。
// ページタイトルのように、途中で変わらない値に使えそう
const pageTitle = '画像解析結果'

// let は、後から別の値を再代入する場合に使う
let selectedImageId = 1

selectedImageId = 2

今の自分は、迷ったらまずconstで書き、再代入が必要になったときだけletを使うようにしたいです。

constで配列やオブジェクトを作った場合でも、中身は変更できます。

// results 自体を別の配列へ入れ替えることはできない
const results = []

// ただし、配列の中へ新しい要素を追加することはできる
results.push({
  id: 1,
  imageName: '画像001'
})

console.log(results)

文字列と条件分岐

値を含む文章を作るときは、テンプレートリテラルが使えそうです。

const imageName = '画像001'
const detectionCount = 3

// バッククォート ` ` で囲むと、${} の中に変数や式を書ける
const message = `${imageName}の検出件数は${detectionCount}件です`

console.log(message)

条件によって処理や表示を変えたいときは、ifを使います。

const detectionCount = 3

// 検出件数が1件以上なら、確認が必要と表示する例
if (detectionCount > 0) {
  console.log('確認が必要です')
} else {
  console.log('問題ありません')
}

短い条件分岐なら、三項演算子も使えます。

const detectionCount = 0

// 条件 ? trueの場合 : falseの場合
const status = detectionCount > 0 ? '確認が必要' : '問題なし'

console.log(status)

三項演算子は短い場合には読みやすいですが、条件が複雑になる場合はifや関数へ分けたほうがよさそうです。

配列とオブジェクト

解析結果のような複数のデータを扱う場合、配列とオブジェクトが大切になりそうです。

配列

配列は、複数の値を順番に持つものです。

// [] で複数の値をまとめる。
// 配列の番号は 0 から始まる点に注意したい
const imageNames = ['画像001', '画像002', '画像003']

console.log(imageNames[0]) // 画像001
console.log(imageNames [vueframework](https://vueframework.com/docs/v3/ja/guide/reactivity-fundamentals.html)) // 画像002

// length で要素数を確認できる
console.log(imageNames.length) // 3

オブジェクト

オブジェクトは、名前: 値の組み合わせで1件の情報を持つものです。

// {} で1件の解析結果を表す。
// 各情報へ名前を付けて持たせる
const result = {
  id: 1,
  imageName: '画像001',
  detectionCount: 3,
  status: '確認が必要'
}

// .プロパティ名 で値を取り出す
console.log(result.imageName)
console.log(result.status)

配列の中にオブジェクトを入れる

解析結果の一覧なら、「解析結果1件分のオブジェクトを複数入れた配列」が使えそうです。

// 複数の解析結果を配列で持つ。
// 1件ごとの情報はオブジェクトとして整理する
const results = [
  {
    id: 1,
    imageName: '画像001',
    detectionCount: 3,
    status: '確認が必要'
  },
  {
    id: 2,
    imageName: '画像002',
    detectionCount: 0,
    status: '問題なし'
  }
]

// 最初の結果の画像名を取り出す
console.log(results[0].imageName)
image.avif 「配列が“結果の一覧”、オブジェクトが“結果1件分の情報”と考えると、少し見分けやすくなってきた。」

Vue3では、このresultsv-forで繰り返し、1件ずつカードや一覧として表示することになりそうです。繰り返し表示する要素には、一意に識別できるkeyを付けることが推奨されています。(Vue.js公式:スタイルガイド) vueframework

関数と配列操作

Vue3・Nuxt4では、クリック時の処理、検索結果の絞り込み、表示内容の組み立てなどを関数として書くことが多そうです。

関数とreturn

関数は、処理へ名前を付けて、必要なときに呼び出せるようにするものです。

// score を受け取り、判定の文字列を返す関数。
// => を使う書き方はアロー関数と呼ばれる
const getEvaluation = (score) => {
  if (score >= 60) {
    return 'Good'
  }

  return 'Bad'
}

// 関数を呼び出し、返り値を変数へ入れる
const evaluation = getEvaluation(80)

console.log(evaluation)

returnは、関数から計算結果を返すために使います。Vue3のcomputedも、表示用の値を計算してreturnするため、ここは特に大切そうです。

mapfilterfind

配列を扱うときは、mapfilterfindがよく出てきそうです。

const results = [
  { id: 1, imageName: '画像001', detectionCount: 3 },
  { id: 2, imageName: '画像002', detectionCount: 0 },
  { id: 3, imageName: '画像003', detectionCount: 1 }
]

// map は、各要素を別の形へ変換した新しい配列を作る。
// APIから受け取った結果を表示用の文章に変える例
const messages = results.map((result) => {
  return `${result.imageName}: ${result.detectionCount}件`
})

// filter は、条件に合う要素だけを残した新しい配列を作る。
// 検出があった結果だけを一覧にしたい場合に使えそう
const detectedResults = results.filter((result) => {
  return result.detectionCount > 0
})

// find は、条件に最初に一致した1件だけを探す。
// 選択したIDから詳細データを探す場合に使えそう
const selectedResult = results.find((result) => {
  return result.id === 2
})

console.log(messages)
console.log(detectedResults)
console.log(selectedResult)
  • map:各要素を変換した新しい配列を作る
  • filter:条件に合う要素だけを残した新しい配列を作る
  • find:条件に合う最初の1件を探す

検索フォームで入力された文字に応じて一覧を絞り込むならfilter、表示用のデータを作り直すならmap、詳細画面の対象をIDで探すならfindが使えそうです。

クラスも触ってみる

クラスは、関連するデータと処理を1つにまとめる書き方です。

JavaScriptの基本として知っておきたいですが、Vue3・Nuxt4のComposition APIでは、画面の状態をrefで持ち、処理を関数やcomposableとして書くことが多そうです。そのため、最初は関数とオブジェクトを優先し、クラスは既存のコードやライブラリを読むための基礎として触れておきたいです。Vue3では以前のフィルター機能が削除され、関数呼び出しか算出プロパティで置き換えることが案内されています。(Vue.js公式:フィルターの削除) vueframework

// クラスは、データ(プロパティ)と処理(メソッド)をまとめる書き方。
// 解析結果1件を扱う例として定義している
class AnalysisResult {
  // constructor は new したときに最初に実行される。
// 受け取った値を、作られたデータのプロパティとして保持する
  constructor(id, imageName, detectionCount) {
    this.id = id
    this.imageName = imageName
    this.detectionCount = detectionCount
  }

  // メソッドは、そのデータに関係する処理を書く場所。
// 検出件数をもとに判定メッセージを返す
  getStatus() {
    if (this.detectionCount > 0) {
      return '確認が必要'
    }

    return '問題なし'
  }
}

// new でクラスから実際のデータを作る
const result = new AnalysisResult(1, '画像001', 3)

console.log(result.imageName)
console.log(result.getStatus())

この例では、resultが画像名・検出件数を持ち、getStatus()で自分の状態から判定を作ります。

ただ、Vue3の一覧画面では、次のようにオブジェクトでデータを持ち、外側の関数で処理を分けたほうが、今の自分には読みやすそうです。

// 画面で扱う解析結果のデータ
const result = {
  id: 1,
  imageName: '画像001',
  detectionCount: 3
}

// データの外側に、判定処理を関数として置く。
// Vueの computed やNuxtの composable へつなげやすそう
const getStatus = (result) => {
  return result.detectionCount > 0
    ? '確認が必要'
    : '問題なし'
}

継承、extendssuper、静的メソッドなどは今回は深追いしません。まずは「クラスはデータと処理をまとめられる書き方」と知り、Vue3・Nuxt4では関数をよく使う、と整理しておきます。

つまずいたところ

通常のJavaScriptの変数と、Vueの画面に反映される値は同じではないところで迷いました。

通常の変数とref

JavaScriptの変数を変更しても、Vueの画面が自動で変わるわけではありません。Vueで値の変化を画面へ反映したい場合には、refを使うと今は理解しています。

image.avif 「値を変えたのに画面が変わらないときは、Vueがその値の変化を追えているかを見直すのかも。」
<script setup>
import { ref } from 'vue'

// ref は、Vueが変化を追跡する値を作る。
// スクリプト内では .value で中の値を扱う
const count = ref(0)

const increment = () => {
  // ボタンを押すたびに値を1増やす
  count.value += 1
}
</script>

<template>
  <!-- テンプレート内では .value を省略して表示できる -->
  <p>件数: {{ count }}</p>

  <!-- クリックすると increment 関数が実行される -->
  <button @click="increment">件数を増やす</button>
</template>

Vueのrefは、値をリアクティブな参照として扱うオブジェクトを返し、スクリプト内ではvalueプロパティで中身にアクセスします。(Vue.js公式:リアクティブの基礎) vueframework

refcomputed

refは元になる値、computedは元の値から作る表示用の値として、今は分けて考えています。

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

// 操作などで直接変更する元の値
const detectionCount = ref(0)

// detectionCount をもとに、画面表示用の判定を作る。
// 元の値が変わると、必要なタイミングで判定も更新される
const status = computed(() => {
  return detectionCount.value > 0 ? '確認が必要' : '問題なし'
})

const addDetection = () => {
  detectionCount.value += 1
}
</script>

<template>
  <p>検出件数: {{ detectionCount }}</p>
  <p>判定: {{ status }}</p>

  <!-- 押すと検出件数が増え、判定表示も変わる -->
  <button @click="addDetection">件数を増やす</button>
</template>

computedはリアクティブな依存関係にもとづいてキャッシュされ、依存する値が変わった場合に再評価されます。検索語と解析結果一覧から「絞り込み後の一覧」を作る場面で使えそうです。(Vue.js公式:算出プロパティ) vueframework

Nuxt4で使えそうなこと

Nuxt4では、Vue3と同じJavaScriptを使いながら、再利用したい処理をcomposableとしてまとめられます。

app/composables/に置いたVue composableは、Nuxtアプリケーション内で自動インポートできます。ただし、そのディレクトリへ置くだけで値がリアクティブになるわけではなく、リアクティブな値はVueのrefreactiveで作る必要があります。(Nuxt4公式:composables) nuxt

// app/composables/useResultFilter.js

// 検索語で解析結果を絞り込む処理を、再利用できる関数としてまとめる。
// 複数の一覧画面で同じ検索処理を使いたい場合に役立ちそう
export const useResultFilter = (results, keyword) => {
  return computed(() => {
    // 検索語が空なら、元の一覧をそのまま返す
    if (!keyword.value) {
      return results.value
    }

    // 大文字・小文字の違いを減らして検索語を整える
    const normalizedKeyword = keyword.value.toLowerCase()

    // 画像名に検索語を含む結果だけを返す
    return results.value.filter((result) => {
      return result.imageName.toLowerCase().includes(normalizedKeyword)
    })
  })
}

この例を実際に使うなら、computedをNuxtの自動インポートで使える状態か、Vueから明示的にimportする必要があるかを、プロジェクト内で確認したいです。

今の理解(メモ)

まだふわっとしていますが、JavaScriptはVue3・Nuxt4で画面の値と処理をつなぐための土台に見えています。

  • JavaScriptは、画面の値、操作、条件分岐、データ取得などを扱う
  • constは再代入しない変数、letは再代入する変数に使う
  • stringnumberbooleannullundefinedは値の種類
  • 配列は複数の値の一覧、オブジェクトは1件の名前付きデータ
  • 関数は処理をまとめ、returnで結果を返す
  • mapは各要素を変換し、filterは条件に合うものだけを残し、findは条件に合う最初の1件を探す
  • クラスはデータと処理をまとめる書き方だが、Vue3・Nuxt4の最初の画面では関数とオブジェクトの優先度が高そう
  • Vue3で画面へ反映したい値はref、元データから表示用の値を作るならcomputed
  • refはスクリプト内で.valueを使い、テンプレート内では.valueを省略できる
  • Nuxt4では、再利用する処理をapp/composables/へ置ける

次にやりたいこと

JavaScriptの基本構文を、Vue3とNuxt4の小さな画面で実際に確認したいです。

  • refで検索語を持ち、入力した文字を画面へ表示する
  • 解析結果の配列をv-forで一覧表示し、id:keyへ使う理由を確認する
  • computedfilterを組み合わせ、検索語に応じて解析結果を絞り込む
  • @clickから関数を呼び、詳細表示のtruefalseを切り替える
  • useResultFilterのようなcomposableを作り、同じ検索処理を別の画面でも使えるか試す

今日の整理

JavaScriptで最初に使いそうな書き方を、Vue3・Nuxt4との関係も含めて整理しました。

分類 書き方 役割 Vue3・Nuxt4での利用イメージ
変数 constlet 値に名前を付ける タイトル、選択中のID
文字列、数値、真偽値 データの種類を扱う 画像名、件数、表示状態
条件 if、三項演算子 条件で処理や値を変える 件数に応じた判定
データ 配列[] 複数の値を持つ 解析結果の一覧
データ オブジェクト{} 1件分の情報を持つ ID、画像名、判定
関数 () => {}return 処理をまとめて結果を返す 検索、絞り込み、判定
配列操作 map 各要素を変換する APIデータを画面用に整える
配列操作 filter 条件に合う要素だけ残す 検索結果の絞り込み
配列操作 find 条件に合う1件を探す IDから詳細データを探す
クラス classnew データと処理をまとめる 既存コードを読むための基礎
Vue3 ref 画面へ反映する値を持つ 検索語、選択中の結果
Vue3 computed 元の値から表示用の値を作る 絞り込み後の一覧
Nuxt4 app/composables/ 再利用する処理を置く 検索・絞り込み処理の共有

おわりに

今回は、Vue3・Nuxt4へ進む前のJavaScriptとして、値・配列・オブジェクト・関数・クラスを整理してみました。クラスも基本として知っておきたい一方で、今の自分がVue3の画面を作るなら、関数、配列操作、refcomputedを優先して手を動かすほうがよさそうです。

画像解析結果をブラウザで見やすく扱うには、一覧データを配列で持つ、検索語で絞り込む、詳細を選ぶ、といったJavaScriptの処理が必要になりそうです。次はVue3で小さな検索一覧を作り、JavaScriptの基本が実際の画面へどうつながるか試してみたいです。

学習中の内容なので、勘違いや理解不足もあると思います。もし気になる点があれば教えてもらえるとうれしいです。

 注意事項
 本ブログに掲載している内容は、私個人の見解であり、
 所属する組織の立場や戦略、意見を代表するものではありません。
 あくまでエンジニアとしての経験や考えを発信していますのでご了承ください。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?