5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クロスマート・テックAdvent Calendar 2024

Day 10

【個人開発】Vue3のカレンダーライブラリを作った

Posted at

今回は、Vue 3を使ってカスタムデートピッカーライブラリ「vue3-datepick」を作成しました。なぜこのライブラリを作ったのか、どういった技術を選定したのかを、細かい実装例や設計思想とともに詳しく解説していきます。最終的にはnpmに公開し、使える形に仕上げました。
リポジトリはこちら: vue3-datepick GitHubリポジトリ

作ったもの

vue3-datepickは、Vue 3コンポーネントとして簡単にインストールして利用できるカレンダーライブラリです。次の機能を持っています:

  • シンプルで直感的なUI
  • 日付フォーマットのカスタマイズ (YYYY-MM-DD, DD/MM/YYYY など)
  • 特定の日付を無効化
  • 日本語を含む多言語対応

作った理由

vue2 PJのvue3 リプレースにおいて、vue2で使用していたカレンダーライブラリと同じ使用感のものがvue3になかったためです。
最近はあまりコミット出来ていませんが、現状一人で開発・メンテしています。

使用例

基本的な使い方は以下の通りです:

<template>
  <DatePick v-model="selectedDate" :disable-dates="disableDates" />
</template>

<script setup>
import { ref } from 'vue';
import DatePick from 'vue3-datepick';

const selectedDate = ref(null);
const disableDates = ['2024-01-01', '2024-12-25'];
</script>

上記のように、v-modelで日付の双方向バインディングを行い、特定の日付(例: 祝日)を無効化することができます。

Props 説明

Prop Name Type Default Description
modelValue string - Vue 3での双方向バインディングを実現するための規定のPropsです。vue3-datepickではdayjsのフォーマットに基づいた年月日文字列を使用します。
yearFirst boolean true 年と月の表示順序を入れ替えるオプションです。trueで年を先に表示、falseで月を先に表示します。
months string[] ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] 各月の表示文字列を配列で渡すことが可能です。日本語では「1月」「01月」「一月」などの表示フォーマットが多岐に渡るため、カスタマイズ性を重視しています。どの言語圏でも違和感なく使用できます。
startWeekOnSunday boolean false 週の開始日を日曜日とするかどうかを設定するオプションです。
weekdays string[] ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] 曜日を文字列配列で上書き可能です。例えば、日本語では「月」「火」などのカスタマイズができます。
disabled boolean false 入力ボックスを無効化するオプションです。
placeholder string - 入力ボックスが空の場合に表示されるプレースホルダー文字列です。
displayFormat string yyyy.MM.dd dayjsのフォーマットに基づいた文字列を指定できます。入力ボックスの表示や、emitされる日付文字列もこのフォーマットに従います。
isDateDisabled (date: Date) => boolean - 各日付の選択を無効化するためのコールバック関数を渡すことが可能です。
yearContent string - 年表示部の接尾辞です。

各技術要素の選定理由

Vite

ビルドツールとしてViteを選定しました。開発サーバーの立ち上がりが速く、ホットリロードも軽快です。さらに、Vue 3との組み合わせがシンプルで、パフォーマンスも向上しました。

npm create vite@latest vue3-datepick --template vue
cd vue3-datepick
yarn install
yarn dev

上記のコマンドで即座に開発環境が整います。

VitePress

ドキュメント生成にはVitePressを採用しました。VueコンポーネントとMarkdownファイルの統合が容易で、プロジェクトのドキュメンテーションがスムーズに進行できます。特に、Viteとの親和性が高く、シンプルな構成で済むのが魅力です。

簡単な設定でおしゃれでいい感じのドキュメントを簡単に作成・ホスティングできます。

import { defineConfig } from 'vitepress'

export default defineConfig({
  title: 'vue3-datepick',
  description: 'A simple and customizable date picker for Vue 3.',
  themeConfig: {
    nav: [
      { text: 'Home', link: '/' },
      { text: 'Guide', link: '/guide/install' },
      { text: 'API', link: '/api/' },
      { text: 'GitHub', link: 'https://github.com/FAL-coffee/vue3-datepick' },
    ],
    sidebar: {
      '/guide/': [
        {
          text: 'Guide',
          items: [
            { text: 'Installation', link: '/guide/install' },
            { text: 'Getting Started', link: '/guide/getting-started' },
            { text: 'Customization', link: '/guide/customization' },
            { text: 'Examples and Demos', link: '/guide/examples' },
          ],
        },
      ],
      '/api/': [
        {
          text: 'API Reference',
          items: [{ text: 'API', link: '/api/' }],
        },
      ],
    },
  },
})

スクリーンショット 2024-11-19 13.44.51.png

Vitest

テストには、軽量かつ高速なVitestを使用しました。Vueコンポーネントのテストに最適で、既存のJestの知識もそのまま活かせます。

以下は日付の無効化機能のテストコードです。

import { mount } from '@vue/test-utils';
import { expect, test } from 'vitest';
import DatePick from './DatePick.vue';

test('should disable specific dates', () => {
  const wrapper = mount(DatePick, {
    props: {
      disableDates: ['2024-01-01'],
    },
  });

  expect(wrapper.find('[data-date="2024-01-01"]').classes()).toContain('disabled');
});

特定の日付を無効化するロジックが正しく動作するかを確認できます。

SCSS + BEM

スタイル管理にはSCSSを用い、クラス名にはBEM(Block Element Modifier)を採用しました。これにより、スタイルの再利用性を高めつつ、可読性を保つことができます。

.date-picker {
  &__input {
    padding: 10px;
    border: 1px solid #ccc;
  }
  &__calendar {
    display: flex;
    flex-direction: column;
  }
  &__day--disabled {
    color: #ddd;
    pointer-events: none;
  }
}

BEMでの構造化により、大規模なプロジェクトでも拡張しやすくなっています。

CI / CD

Release → npm publish

リリース作業はGitHub Actionsを使って自動化しています。特定のタグをプッシュするだけで、npmに自動的にパッケージが公開されます。

name: Publish

on:
  push:
    tags:
      - 'v*.*.*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: npm ci
      - run: npm publish --access public

これにより、リリースフローの自動化が実現し、ミスが減りました。

Test, Lint, Stylelint, and Prettier Checks

コードの品質を維持するために、テストやLint、Stylelint、PrettierによるチェックをCIに組み込んでいます。すべてのプルリクエストに対して自動的にこれらのツールが走り、クリーンなコードベースを保ちます。

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: npm ci
      - run: npm run lint
      - run: npm run prettier --check

これでコードの一貫性とスタイルの整合性を保つことができます。

Vercel(VitePress)

Vercelを使って、VitePressで作成したドキュメントをホスティングしています。
Vercelはデプロイが簡単で、プレビュー環境も提供してくれるため、ドキュメントの更新がスムーズに行えます。

まとめ

Vue 3を用いて、軽量かつカスタマイズ性の高いデートピッカーライブラリを開発しました。Vite、VitePress、Vitest、SCSS + BEMといった技術スタックを組み合わせ、快適な開発体験とモジュール性を重視した設計です。さらに、GitHub Actionsを用いたCI/CDパイプラインにより、リリース作業の自動化とコード品質の維持も実現しました。

今後も継続的に改善していく予定です。興味があればぜひvue3-datepickをチェックしてみてください!

5
2
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
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?