Skip to content
This repository has been archived by the owner on May 25, 2024. It is now read-only.

migrate to typescript #226

Merged
merged 8 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {
root: true,
env: {
node: true,
'vue/setup-compiler-macros': true
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser'
},
extends: [
'plugin:vue/vue3-recommended',
'eslint:recommended',
'@vue/eslint-config-prettier'
],
root: true,
env: { node: true },
plugins: ['@typescript-eslint'],
extends: ['plugin:vue/vue3-recommended', '@vue/eslint-config-prettier'],
rules: {
'vue/html-closing-bracket-newline': [
'error',
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
Expand Down
97 changes: 36 additions & 61 deletions docs/component.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# 商品をコンポーネント化する

## 本章の概要とゴール

本章では、1 つ 1 つの商品を表示するコードをコンポーネントとして分離し、再利用できるようにプログラムを改修していきます。
本章を実践すると、プログラムの一部を再利用できるコンポーネントとして切り出したり、 `props` を使ってコンポーネントに必要な情報を渡すことができるようになります。

Expand All @@ -9,7 +10,7 @@
Vue.js ではテンプレート、ロジック、そしてスタイルを 1 つのファイルにまとめることで、単一ファイルコンポーネント(`Single File Components`、略称 `SFC`)として利用することができます。`SFC` は `<script setup>` 内で `import` することで、テンプレートで直接使用することが可能となります。

```vue{2,6}
<script setup>
<script setup lang="ts">
import MyComponent from './MyComponent.vue'
</script>

Expand All @@ -33,18 +34,19 @@ import MyComponent from './MyComponent.vue'
<<< @/../examples/event/src/App.vue#script

## 一部をモジュールとして切り出す

モジュールとして切り出す時、どの範囲で切り出すか迷うかもしれません。そのような場合は、再利用可能という観点で考えてみてもよいかもしれません。今回の場合、商品の部分は、`v-for` の中で何度も呼ばれているので、この範囲で切り出してみるのが良さそうです。

### コンポーネントの作成

`Card` コンポーネントとして切り出しますが、`src` ディレクトリの下に新たに `components` ディレクトリを作成し、そこに `Card.vue` ファイルを作成します。今後コンポーネントを新たに作っていく場合は、`components` ディレクトリに格納していくとよいでしょう。作成後は下記のようなディレクトリ構成になっていると思います。
`Card` コンポーネントとして切り出しますが、`src` ディレクトリの下に新たに `components` ディレクトリを作成し、そこに `Card.vue` ファイルを作成します。今後コンポーネントを新たに作っていく場合は、`components` ディレクトリに格納していくとよいでしょう。作成後は下記のようなディレクトリ構成になっていると思います。

```
src
┣━ components
┃ ┗━ Card.vue
┣━ App.vue
┗━ main.js
┗━ main.ts
```

次にいよいよモジュールを切り出す作業に入ります。以下のハイライト部分を `Card.vue` に移します。また、`pricePrefix()` や関連する `style` も一緒に移します。
Expand All @@ -66,26 +68,23 @@ src
#### Card.vue

```vue
<script setup>
/**
* 価格を3桁ごとのカンマ付きで返す
* @param {number} price 価格
*/
function pricePrefix(price) {
<script setup lang="ts">
/** 価格を3桁ごとのカンマ付きで返す */
function pricePrefix(price: number): string {
return price.toLocaleString()
}
</script>

<template>
<div class="thumbnail">
<img
:src="item.image"
alt="">
<img :src="item.image" alt="" />
</div>
<div class="description">
<h2>{{ item.name }}</h2>
<p>{{ item.description }}</p>
<span>¥<span class="price">{{ pricePrefix(item.price) }}</span></span>
<span
>¥<span class="price">{{ pricePrefix(item.price) }}</span></span
>
</div>
</template>

Expand Down Expand Up @@ -118,6 +117,7 @@ function pricePrefix(price) {
```

## Card コンポーネントを使用する

切り出しができたので、作成したコンポーネントを `App.vue` で使えるようにしましょう。

#### App.vue / template
Expand Down Expand Up @@ -146,7 +146,7 @@ function pricePrefix(price) {
#### App.vue / script

```vue{3}
<script setup>
<script setup lang="ts">
import { ref } from 'vue'
import Card from './components/Card.vue'

Expand Down Expand Up @@ -185,42 +185,24 @@ import Card from './components/Card.vue'
#### Card.vue / script

```vue{2-23}
<script setup>
defineProps({
name: {
type: String,
default: '',
required: false
},
description: {
type: String,
default: '',
required: false
},
price: {
type: Number,
default: 0,
required: false
},
image: {
type: String,
default: '',
required: false
},
});
<script setup lang="ts">
defineProps<{
name: string
description: string
price: number
image: string
}>()

// 省略

</script>
```

`defineProps` の中に受け取る `props` を書いていきます。`type` は型、`default` は初期値、`required` は必須要素を表しています。

::: tip ヒント
`defineProps` とこのあと紹介する `defineEmits` は `<script setup> ` 内でのみ使用可能なコンパイラマクロとなっているため、`import` する必要はありません。
:::

### App.vueから値を渡す準備をする
### App.vue から値を渡す準備をする

`Card.vue` の `defineProps` で定義した値を `template` 内で渡していきます。

Expand Down Expand Up @@ -260,6 +242,7 @@ defineProps({
`Card` コンポーネントでは `pricePrefix` 関数を使用しています。このように、同じコンポーネント内で処理が完結している場合はよいですが、呼び出されている親のコンポーネントの関数を実行したい時があります。今回は例として、`Card` コンポーネントに「売り切れ」のボタンを作成し、クリックすると非表示になる、という処理を追加してみます。

### Card コンポーネントで emits の定義をする

Vue.js では `emits` オプションが使えます。`emits` オプションは、子のコンポーネント内で親のコンポーネントに発行できるイベントを定義できます。

今回では子のコンポーネントで「売り切れ」のイベントを発行して、親のコンポーネントで `items` を書き換える、という流れになります。現状では `Card` コンポーネントは渡された情報を表示するのみで、どの `item` か特定できる情報がないので、`id` も渡すように修正します。`defineProps` も忘れず修正しましょう。
Expand All @@ -278,22 +261,14 @@ Vue.js では `emits` オプションが使えます。`emits` オプション
#### Card.vue / script

```vue{3-7}
<script setup>
defineProps({
id: {
type: Number,
default: null,
required: false
},
name: {
type: String,
default: '',
required: false
},

// 省略

})
<script setup lang="ts">
defineProps<{
id: number
name: string
description: string
price: number
image: string
}>()

// 省略

Expand All @@ -303,15 +278,15 @@ defineProps({
`<script setup>` の中で `emits` を使用するためには `defineEmits` の API を使用します。`defineProps` と同様に `<script setup>` の中で自動的に使えるようになっているため、`import` は不要です。

```vue{9}
<script setup>
<script setup lang="ts">

// 省略

function pricePrefix(price) {
function pricePrefix(price: number): string {
return price.toLocaleString()
}

const emit = defineEmits(['sold-out'])
const emit = defineEmits<{ 'sold-out': [id: number] }>()
</script>
```

Expand Down Expand Up @@ -345,11 +320,11 @@ const emit = defineEmits(['sold-out'])
`Card` コンポーネントには `sold-out` の `emits` を受け取った場合に `changeSoldOut` が実行されるように設定しました。次に、実行される `changeSoldOut` を定義します。

```vue{5-8}
<script setup>
<script setup lang="ts">

// 省略

function changeSoldOut(id) {
function changeSoldOut(id: number) {
const pickElm = items.value.find(item => item.id == id)
pickElm.soldOut = true
}
Expand Down
13 changes: 9 additions & 4 deletions docs/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
Ok to proceed? (y) -> y
```

以降の質問には、基本的に `No` を選択して進めます。
以降の質問には、基本的に `No` を選択して進めます。\
TypeScript だけは `Yes` を選択しましょう。

::: tip ヒント
矢印キーでアンダースコアを移動させることで項目を選択します。
Expand All @@ -40,7 +41,7 @@

```
Vue.js - The Progressive JavaScript Framework
? Add TypeScript? › No / Yes -> No
? Add TypeScript? › No / Yes -> Yes
? Add JSX Support? › No / Yes -> No
? Add Vue Router for Single Page Application development? › No / Yes -> No
? Add Pinia for state management? › No / Yes -> No
Expand Down Expand Up @@ -86,6 +87,9 @@
├── node_modules
├── package-lock.json
├── package.json
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.build.json
├── public
│   └── favicon.ico
├── src
Expand All @@ -104,8 +108,9 @@
│   │   ├── IconEcosystem.vue
│   │   ├── IconSupport.vue
│   │   └── IconTooling.vue
│   └── main.js
└── vite.config.js
│   ├── main.ts
│   └── vite-env.d.ts
└── vite.config.ts

6 directories, 19 files
```
Expand Down
2 changes: 1 addition & 1 deletion docs/event.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ Vue.js でイベントリスナーを登録するには `v-on` というディ
```

```vue
<script setup>
<script setup lang="ts">
// ...省略

function alertDialog() {
Expand Down
Loading
Loading