🔖
UIフレームワーク依存に立ち向かうための、Vue.js コンポーネント実装
UIフレームワーク依存に立ち向かうための、Vue.js コンポーネント実装
TL;DR
- iCAREのフロントエンド開発では、通常プロジェクトとは別軸でデザインシステムPJを進行
- 基本はデザインの共通化、統一化がメインで、UIフレームワークを交換可能にするコンポーネントも併せて作成している
Vue.jsにおけるUIフレームワークとは?
Vue.jsを拡張した、コンポーネントを提供するフレームワーク
- Vuetify
- BootstrapVue
- Bulma
※ BootstrapやTailwind、Bulma等はCSSフレームワークの位置付け
Buefyの依存から脱却したい...
- やめ太郎さんのQiitaに以前、ライブラリのラッパーについての記事がありました
ワイ「なに!?ライブラリをラップするやと!?」 - Qiita
- iCAREのフロントエンドとしては、Buefyを使い続けるかどうかの議論は常に行われていて、いつでもBuefyから別のUIフレームワークまたはCSSフレームワークに乗り換えが行えるように、
交換可能なコンポーネント
なコンポーネントの実装を行っています
交換可能なコンポーネントとは?
- 再利用可能であること(Interchangeable)
- UIフレームワークに依存しない形で、実装するコンポーネント(Reusable)
- 併せて、Interchangeable & Reusable components?
- 要は、導入しているUIフレームワークを移行したい場合でも、大きなコストを掛けずに移行できるコンポーネント
どうやって実装するの?
モチベーション
といったペインを解決したい
このコンポーネントはデザインシステム化の一環であり、全体的なデザインの共通化にも繋がる
交換可能なモーダルコンポーネント
- 画像のようなモーダルを実装する
- Buefyのb-modalを利用して、ラッパーコンポーネントを実装
イメージ図
- アイデアをホワイトボードに書き出してみる
- メモの新規作成と編集で使い回すので削除は非表示の可能性あり
モーダルコンポーネントの実装
carely-modal.vue
<template>
<div class="modal-card">
<slot name="header" />
<slot name="content" />
<footer class="modal-footer">
<slot name="footer-left" />
<slot name="footer-right" />
</footer>
</div>
</template>
<style lang="scss" scoped>
.modal-card {
width: 970px;
height: 700px;
}
.modal-footer {
justify-content: space-between;
}
.footer-right-container {
margin-left: auto;
}
</style>
parent.vue
<template>
<carely-modal>
<template #header>
<carely-modal-header title="タイトル" @close="close" />
</template>
<template #content>
<b-field label="メモ">
<b-input v-model="memo" type="textarea" />
</b-field>
</template>
<template #footer-left>
<b-button type="is-danger" class="width-100" @click="delete">
削除
</b-button>
</template>
<template #footer-right>
<-- TODO: carely-modal-footerを作る -->
<b-button type="is-text" class="width-100" @click="close">キャンセル</b-button>
<b-button type="is-primary" class="width-100" @click="save">保存</b-button>
</template>
</carely-modal>
</template>
交換可能なChartコンポーネント
Chart.jsのラッパーコンポーネントを作る
- Chart.js には Vueコンポーネントとして拡張されたvue-chartjsがある
- 各チャートタイプを呼び出すのではなく、タイプごとにVue インスタンス作成するコンポーネントを実装
carely-chart.ts
import AdditionalChartContent from '@/component/page/stress_check/surveys/additional-chart-content.vue'
import { InsidePropsType, OutsidePropsType } from '@icare-jp/vue-props-type'
import { defineComponent } from '@vue/composition-api'
import { HorizontalBar, Scatter } from 'vue-chartjs'
const chartTypeConverter = (chartType: ChartType) => {
// ここにtypeを追加する
switch (chartType) {
case 'Horizontal':
return HorizontalBar // コンポーネント名
case 'Scatter':
return Scatter
default:
throw new Error('chartType does not exist.')
}
}
const chartGenerator = (chartType: ChartType) =>
defineComponent({
components: { AdditionalChartContent },
extends: chartTypeConverter(chartType),
props: {
chartOptions: {
type: Object,
required: true,
},
height: {
type: Number,
required: false,
default: null,
},
styles: {
type: Object,
required: false,
default: () => ({ width: '100%', height: '280px' }),
},
},
mounted() {
this.renderChart(this.chartOptions.data, this.chartOptions.options)
},
})
// ここでチャートの種類を増やす
export const CarelyHorizontalChart = chartGenerator('Horizontal') // 横棒
export const CarelyScatterChart = chartGenerator('Scatter') // 散布図
- extendsもしくはmixinでチャートのタイプを指定するため、今回はReduxのAction Typeのように、文字列をchartGeneratorの引数に渡し、extendsでchartTypeConverterでチャートタイプ名を返すようにする
Discussion