Vue.js + Onsen UIで作る晩ご飯ランダムスロット

この記事は [クソアプリ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/kuso-app) 2日目の記事です。
拙作の紹介と簡単にOnsen UIのチュートリアルを記します。

## 前置き
私は普段外食が多いのですが、毎日何食べるか決めるのが面倒。
リストアップしてアプリに決めてもらおう！ということでサクッと作りました。

## 成果物
[メシガチャ！](https://meshi.tokyo/) 
![onsen-demo.gif](https://qiita-image-store.s3.amazonaws.com/0/239966/6847bf41-f599-e6d5-d2d4-09b0b3ac6f2f.gif)

~~健康に悪そうな食生活だなぁ。~~

## 使用技術など
* Vue.js, Onsen UIにて実装。
* データはセッションに保持しております。
* ➕ボタンでリストに追加した値をランダムに排出する形となっております。
* PWAにも対応しているため（UIのみ）、「ホーム画面に追加」することでネイティブアプリライクなUIを体感できます。

## Onsen UIについて
今回はネイティブのようなUIを実装したかったこともあり、[Onsen UI](https://ja.onsen.io/)を使用してみました。
![20180211235953.png](https://qiita-image-store.s3.amazonaws.com/0/239966/10aebbdf-5dc6-4eeb-fd27-6b4c80fa9648.png)
#### :mag:Onsen UIとは
>モバイルアプリに特化した、ネイティブのようなパフォーマンスに優れたUIコンポーネントが自慢です。タブ、サイドメニュー、ナビゲーションといった共通デザインだけでなく、リストやフォームといった様々なデザインを網羅しています。すべてのコンポーネントでiOSとAndroidマテリアルデザインに対応し、実行する端末にあわせて自動的にスタイルを切り替えます。Onsen UIを使うことで、AndroidとiOS向けアプリのソースコードが遂に共通化されます。

[公式サイト](https://ja.onsen.io/)より引用

#### Onsen UI for Vue
Vue.js版は[こちら](https://ja.onsen.io/vue/)になります。
Vue CLIからセットアップしてみます。

#### 環境

```
$ node -v
v10.5.0
$ npm -v
6.1.0
```
それでは公式に従いセットアップします。
vue init後の質問は全てデフォルトのままにしております。

```
$ vue init OnsenUI/vue-pwa-webpack hello-onsenui
$ cd hello-onsenui
$ npm install
$ npm run dev
```

セットアップされたデフォルトのレイアウトは以下のようになります。
![onsen-demo.gif](https://qiita-image-store.s3.amazonaws.com/0/239966/383a1693-014d-5040-15d0-47eb73b2c4f8.gif)

専用のコンポーネントを使う際は、src配下の設定ファイルの各コンポーネントを有効化する必要があります。
使用頻度の高いコンポーネントが初期状態ではコメント化されているので注意が必要そうです。

```javascript:vue-onsen-component.js
// Add your components:

// export { default as VOnsActionSheet } from 'vue-onsenui/esm/components/VOnsActionSheet'
// export { default as VOnsActionSheetButton } from 'vue-onsenui/esm/components/VOnsActionSheetButton'
// export { default as VOnsAlertDialog } from 'vue-onsenui/esm/components/VOnsAlertDialog'
// export { default as VOnsAlertDialogButton } from 'vue-onsenui/esm/components/VOnsAlertDialogButton'
// export { default as VOnsBackButton } from 'vue-onsenui/esm/components/VOnsBackButton'
// export { default as VOnsBottomToolbar } from 'vue-onsenui/esm/components/VOnsBottomToolbar'
// export { default as VOnsButton } from 'vue-onsenui/esm/components/VOnsButton'
export { default as VOnsCard } from 'vue-onsenui/esm/components/VOnsCard'
// export { default as VOnsCarousel } from 'vue-onsenui/esm/components/VOnsCarousel'
// export { default as VOnsCarouselItem } from 'vue-onsenui/esm/components/VOnsCarouselItem'
// export { default as VOnsCheckbox } from 'vue-onsenui/esm/components/VOnsCheckbox'
export { default as VOnsCol } from 'vue-onsenui/esm/components/VOnsCol'
// export { default as VOnsDialog } from 'vue-onsenui/esm/components/VOnsDialog'
// export { default as VOnsFab } from 'vue-onsenui/esm/components/VOnsFab'
export { default as VOnsIcon } from 'vue-onsenui/esm/components/VOnsIcon'
// export { default as VOnsInput } from 'vue-onsenui/esm/components/VOnsInput'
// export { default as VOnsLazyRepeat } from 'vue-onsenui/esm/components/VOnsLazyRepeat'
export { default as VOnsList } from 'vue-onsenui/esm/components/VOnsList'
export { default as VOnsListHeader } from 'vue-onsenui/esm/components/VOnsListHeader'
export { default as VOnsListItem } from 'vue-onsenui/esm/components/VOnsListItem'
export { default as VOnsListTitle } from 'vue-onsenui/esm/components/VOnsListTitle'
// export { default as VOnsModal } from 'vue-onsenui/esm/components/VOnsModal'
// export { default as VOnsNavigator } from 'vue-onsenui/esm/components/VOnsNavigator'
export { default as VOnsPage } from 'vue-onsenui/esm/components/VOnsPage'
// export { default as VOnsPopover } from 'vue-onsenui/esm/components/VOnsPopover'
// export { default as VOnsProgressBar } from 'vue-onsenui/esm/components/VOnsProgressBar'
// export { default as VOnsProgressCircular } from 'vue-onsenui/esm/components/VOnsProgressCircular'
// export { default as VOnsPullHook } from 'vue-onsenui/esm/components/VOnsPullHook'
// export { default as VOnsRadio } from 'vue-onsenui/esm/components/VOnsRadio'
// export { default as VOnsRange } from 'vue-onsenui/esm/components/VOnsRange'
// export { default as VOnsRipple } from 'vue-onsenui/esm/components/VOnsRipple'
export { default as VOnsRow } from 'vue-onsenui/esm/components/VOnsRow'
// export { default as VOnsSearchInput } from 'vue-onsenui/esm/components/VOnsSearchInput'
// export { default as VOnsSegment } from 'vue-onsenui/esm/components/VOnsSegment'
// export { default as VOnsSelect } from 'vue-onsenui/esm/components/VOnsSelect'
// export { default as VOnsSpeedDial } from 'vue-onsenui/esm/components/VOnsSpeedDial'
// export { default as VOnsSpeedDialItem } from 'vue-onsenui/esm/components/VOnsSpeedDialItem'
export { default as VOnsSplitter } from 'vue-onsenui/esm/components/VOnsSplitter'
export { default as VOnsSplitterContent } from 'vue-onsenui/esm/components/VOnsSplitterContent'
export { default as VOnsSplitterMask } from 'vue-onsenui/esm/components/VOnsSplitterMask'
export { default as VOnsSplitterSide } from 'vue-onsenui/esm/components/VOnsSplitterSide'
// export { default as VOnsSwitch } from 'vue-onsenui/esm/components/VOnsSwitch'
// export { default as VOnsTab } from 'vue-onsenui/esm/components/VOnsTab'
// export { default as VOnsTabbar } from 'vue-onsenui/esm/components/VOnsTabbar'
// export { default as VOnsToast } from 'vue-onsenui/esm/components/VOnsToast'
export { default as VOnsToolbar } from 'vue-onsenui/esm/components/VOnsToolbar'
export { default as VOnsToolbarButton } from 'vue-onsenui/esm/components/VOnsToolbarButton'
```

## Special thanks
[Onsen UI for Vue](https://ja.onsen.io/vue/)
[Onsen UI 2でアプリを作ってわかったこと](https://qiita.com/puku0x/items/3f2ece43c67742fd67ea)