PrimeVueコンポーネントの使い方

# PrimeVueとは？
PrimeVue とは Vue.js で利用できる包括的な UI コンポーネントライブラリのことです。カスタマイズが容易で、効率的な Web アプリケーションの開発を実現できます。

https://primevue.org/

# 事前準備
PrimeVue を利用する前に、Vue.js や PrimeVue のインストールを行う必要があります。しかし、本記事は PrimeVue の使い方を説明するものなので、各種インストールの詳細な説明は省略します。

### Vue.js のインストール
+ Node.js をインストールして npm コマンドを使えるようにします
+ CLI に npm などを用いて PC にインストールします
+ `npm create vue@latest` で最新バージョンの Vue.js でプロジェクトを作成します

詳しくは以下のサイトを参照してください。

https://ja.vuejs.org/guide/quick-start.html

### PrimeVue のインストール
+ `npm install primevue @primevue/themes` で PrimeVue をインストールします
+ Vue プロジェクトの main.js(または main.ts) で PrimeVue をインポートします

詳しくは以下のサイトを参照してください。（Vite によるインストール方法です）

https://primevue.org/vite

---
以下に実行環境を記述します。
+ MacOS Sequoia: 15.0.1
+ VScode: 1.94.2
+ Vue: 3.5.12
+ PrimeVue: 4.1.1

# Componentsページの見方
PrimeVue公式ドキュメントのサイドメニューにはPrimeVueの利用方法のあらゆることが記載されています。今回は特に **Components** に焦点を当てていきます。

![PrimeVue公式のサイドメニュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/b7b933d7-eaab-8ede-041d-71ce12a06dca.png)

試しに **InputText** コンポーネントを選択します。
コンポーネントページには FEATURES, API, THEMING, PASS THROUGH タブがあります。それぞれ詳しく見ていきます。

### FEATURES
ここにはコンポーネントの基本的な使い方が記載されています。「ブラウザの表示 → コード」の流れがセットになって書かれています。コードのところにある `< >`のようなボタンで全体を見ることができます。

![toggleボタン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/55a1c0bb-d94e-4364-a86e-79c532144f04.png)


主な流れはVueファイルの中で、
```vuejs
<script setup>
import XxxXxx from 'primevue/xxxxxx';
</script>
```

のように script タグの中でインポートして、

```vuejs
<template>
  <XxxXxx />
</template>
```

のように、template タグの中で使用します。
試しに簡単に InputText を使用してみます。手っ取り早く実装したいので、App.vueに書いていきます。

```vuejs:App.vue
<script setup>
import { ref } from 'vue'
import InputText from 'primevue/inputtext'; // ここで PrimeVue コンポーネントをインポートします

const value = ref("");
</script>

<template>
  <p>InputText</p>
  <InputText type="text" v-model="value" /> <!-- ここでコンポーネントを使用します -->
</template>
```

↓↓↓

![InputTextの実装例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/cb442b88-60e7-d16d-4b62-b5752bcfe6bb.png)

これだけで登録フォームによくある入力ボックスを実装することができます。

`const value = ref("");`
で定義した value 変数は、例えば以下のように利用できます。

```vuejs:App.vue
<script setup>
...
</script>

<template>
  <InputText type="text" v-model="value" />
  <p>{{ value }}</p> <!-- このコードを追記しました -->
</template>
```

↓↓↓

![InputText-ezgif.com-video-to-gif-converter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/c5c498a9-1ac4-761c-c651-48b88908545e.gif)

特にスタイルを指定しておりませんが、
ホバー時やアクション時に PrimeVue のデフォルトのスタイルが適用されています。
PrimeVue が効率的な Web アプリケーションの開発に寄与していることがわかるかと思います。

### API
各コンポーネントの詳細な仕様を知るには、API タブを参考にすると良いでしょう。いくつかの項目があるうち、一部を紹介します。

#### Props
Props を使うことでコンポーネントのタグ内でデータを送り、レイアウトを指定することができます。例えば InputText の場合、`size`という Props に `small`か`large`を指定して入力ボックスの大きさを変えることができます。（使い方は FEATURES にある例を参考にしてください）
他にも例えば`fluid`というものがあり、こちらを指定すると入力ボックスの width が 100% になります。`fluid`の Type は`boolean`なので、タグ内で`fluid`と記載するだけでスタイルが適用されます。

```vuejs:App.vue
<script setup>
...
</script>

<template>
<div>
    <InputText type="text"  />
</div>
<div>
    <InputText type="text" fluid />
</div>
</template>
```

↓↓↓

![fluidの例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/dce9cb0c-0bc5-f70b-7af4-44df23523b26.png)

#### Emits
Emitsを使うことでコンポーネントのイベントを指定することができます。今回は Select コンポーネントを利用します。
Select ページの API → Emits には `focus`があります。これはブラウザで Select コンポーネントをクリックしてアクティブにしたときに発火されるイベントです。

```vuejs:App.vue
<script setup>
import { ref } from 'vue';
import Select from 'primevue/select';

const selectedCity = ref("");
const cities = ref([
  { name: 'New York' },
  { name: 'Rome' },
]);

const focusResultMessage = ref("入力してください");

// focus イベントの内容をここで定義しています
const focusSelect = (event) => {
  focusResultMessage.value = ""
};
</script>

<template>
  <p>{{ focusResultMessage }}</p>
  <Select
    v-model="selectedCity"
    :options="cities"
    optionLabel="name"
    @focus="focusSelect" 
  />
  <!-- タグ内に focus イベントを記入します -->
</template>
```

↓↓↓

![selectfocus-ezgif.com-video-to-gif-converter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/4ff33fc2-3293-cd20-d372-d32f5bac8dc2.gif)

Select をクリックする
→ focusSelect イベントが走る
→ focusResultMessage の値が空になる
→ 画面から消える

といった流れになっています。

また、Emits の Parameters に `event` が指定されている場合、これをメソッドの中で利用することができます。Select の focus イベントにもこのパラメータがあるので、`console.log()`と Google の検証ツールで中身を見てみます。

```vuejs:App.vue
<script setup>
...

const focusSelect = (event) => {
  console.log("event", event);
};
</script>

<template>
...
</template>
```

↓↓↓

![focus_eventの中身.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/939daba1-1f63-36ed-1910-79fc8a35eb5d.png)

#### Slots
Slots はコンポーネントをより自由にカスタマイズするときに使用します。例えば、Select の Slots に `dropdownicon`があるので、このアイコンを変えてみます。

```vuejs:App.vue
<script setup>
import Select from 'primevue/select';

</script>

<template>
  <!-- 左のSelect -->
  <Select style="margin-right: 10px;" />
  
  <!-- 右のSelect -->
  <Select >
    <template #dropdownicon>
      <span>▼</span>
    </template>
  </Select>
</template>
```

↓↓↓

![selectのslotsの使用例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/9289b398-8c59-2244-83bd-975eaf0d01a6.png)


#### Methods
Methods にはコンポーネントの`ref`属性に指定した変数で使えるメソッドが書かれています。これは後ほど [ref属性の活用方法](#ref属性の活用方法) で解説します。

### THEMING
THEMINGタグに書かれている内容はコンポーネントのスタイルを指定するのに、役立ちます。

#### CSS Classes
その名の通り、コンポーネントが利用している CSS のクラス名になります。例えば Select コンポーネントの場合、`p-select`や`p-select-dropdown`などがあり、これらの用途は検証ツールで確認することができます。

![selectのclassのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/4158efac-4f56-1643-26ec-9334249e8228.png)

#### Design Tokens
Design Tokens とはアプリ全体で一貫性のあるデザインを実現するための基盤となります。色やフォントサイズなどのデザイン要素を変数のように定義しています。
例えば Select コンポーネントの場合、select.background には `-p-select-background`という変数が使われています。これが実際何を指しているかは Google の検証ツールで見ることができます。

![designTokenの例のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/fa5f97c4-de64-9d0a-6092-525c763cbd0a.png)

`-p-select-background`は`#ffffff`であり、これが Select コンポーネント全体の背景色になっています。

色に関してはサイドメニューの`Theming`に一例が載っています。

### PASS THROUGH
Pass Through はコンポーネントのスタイリングやカスタマイズを柔軟に行うための機能です。このタグページに記載されている `Label`と、API Slots の`pt`属性を利用してコンポーネントのスタイルを指定することができます。
例えば Select コンポーネントの `root`を用いて、背景色を変更してみます。

```vuejs:App.vue
<script setup>
import Select from 'primevue/select';

const ptSelect = {
  root: {
    style: {
      background: '#FFFF00'
    }
  }
};
</script>

<template>
  <Select :pt="ptSelect" />
</template>
```

または

```vuejs:App.vue
<script setup>
import Select from 'primevue/select';

const ptSelect = {
  style: {
    background: '#FFFF00'
  }
}

</script>

<template>
  <Select :pt:root="ptSelect" /> <!-- 'root'を移動させました -->
</template>
```

↓↓↓

![ptで色変更.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/143a55ea-0841-1149-36b0-7a5bf596cb14.png)

Pass Through は他の利用法もありますので、詳細はサイドメニューの`Pass Through`を参考にしてください。

# コンポーネントのスタイルを変更する方法

### pass throughを使う
[APIのPASS THROUGH](#pass-through) で説明した通り、`pt`属性を指定してスタイルを変更することができます。

### class 属性を付与する
通常のHTMLタグのように、PrimeVue のコンポーネントも class をつけることができます。これにより、CSS でスタイルを追加したり、上書きしたりできます。

```vuejs:App.vue
<script setup>
import Select from 'primevue/select';
</script>

<template>
  <Select />
  <Select class="my-class"/>
</template>

<style scoped>
.my-class {
  margin-left: 10px; /* スタイルを追加します */
  background: #00FF00; /* スタイルを上書きします */
}
</style>
```

↓↓↓

![classを指定するのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/36c12368-3c29-7690-344e-889ef2affd77.png)

### 直接コンポーネントの class を変更する
[THEMING](#theming) で触れたように、PrimeVue ではコンポーネントで使用している class 名が明記されています。Select コンポーネントの場合、`p-select`や`p-select-dropdown`などがあります。これらを直接利用してスタイルを変更することができます。

```vuejs:App.vue
<script setup>
import Select from 'primevue/select';
</script>

<template>
  <div>
    <Select />
    <Select />
  </div>
</template>

<style scoped>
/* :deep()を使用します */
:deep(.p-select) { 
  background: #00FFFF;
  margin-right: 10px;
}
</style>
```

↓↓↓

![primevueのclassを直接使用するのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/49b261c5-43a0-51b5-8db6-a9bcbd428927.png)


CSSに `:deep()` を使うことでコンポーネント内部の class にアクセスし、デザインを変更することができます。
詳しくは [SFC CSS 機能](https://ja.vuejs.org/api/sfc-css-features) を参考にしてください。


# ref属性の活用方法

PrimeVue コンポーネントでは `ref`属性を用いて DOM要素に直接アクセスすることができます。詳しくは [テンプレート参照](https://ja.vuejs.org/guide/essentials/template-refs) を参考にしてください。
コンポーネントの中には API で Method が定義されているものがあります。例えば、DataTable コンポーネントでは `exportCSV` が定義されています。

```vuejs:App.vue
<script setup>
import { ref } from 'vue'
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import Button from 'primevue/button';

const products = ref([
  { code: 'f230fh0g3', name: 'Bamboo Watch', category: 'Accessories', quantity: 24 },
  { code: 'nvklal433', name: 'Black Watch', category: 'Accessories', quantity: 61 },
]);

const dt = ref(null); // この変数を DataTable タグの ref に格納します
const exportCSV = () => {
  dt.value.exportCSV() // ここで Method を呼び出しています
}

</script>

<template>
  <div>
  <DataTable :value="products" ref="dt">
    <Column field="code" header="Code"></Column>
    <Column field="name" header="Name"></Column>
    <Column field="category" header="Category"></Column>
    <Column field="quantity" header="Quantity"></Column>
  </DataTable>
  <Button label="エクスポート" @click="exportCSV" />
  </div>
</template>

<style scoped>
```

↓↓↓

![datatable例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/9690e650-b4d5-e833-07c4-03777973e3a7.png)

ここで「エクスポート」ボタンをクリックすると、CSVファイルをエクスポートできます。このファイルを Excel で開いてみます。

↓↓↓

![excelにエクスポート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/eb36096c-c616-a67d-01fa-5adb74bd9d4a.png)


---
また、`ref`ではコンポーネントが扱っているデータを取得することができます。fileUpload コンポーネントがわかりやすいので、これを例にします。

```vuejs:App.vue
<script setup>
import { ref } from 'vue'
import FileUpload from 'primevue/fileupload';

const fileupload = ref(null);
const onSelectedFiles = () => {
  console.log("fileupload.value.files", fileupload.value.files) // fileupload の files を参照することができます
}

</script>

<template>
  <div>
  <FileUpload
    ref="fileupload"
    name="demo[]"
    url="/api/upload"
    @select="onSelectedFiles"
  >
    <template #empty>
      <div>
        <p>Drag and drop files to here to upload.</p>
      </div>
    </template>
  </FileUpload>
  </div>
</template>
```

↓↓↓

![fileUpload-ezgif.com-video-to-gif-converter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2405417/f32fdd3e-ded0-7fe9-3d29-54cd1e2ff3d4.gif)

`fileupload` の中の `files` オブジェクトに、ドラッグ&ドロップした画像のデータがあります。私はこれを利用して、登録した写真をドラッグ&ドロップで入れ替える機能を実装したことがあります。

---

以上で、私がよく利用している PrimeVue の扱い方の説明をお伝えしました。
最後までご愛読いただき、ありがとうございました。