重要: ガイドの一部は現在翻訳中です。また、現時点での Vue 2 バインディングは α 版 のため、このガイドの内容は API 変更や機能追加に伴い頻繁に変更されます。ご注意ください(2017/02/03)。

プロジェクトを始める

NPM からダウンロード

$ npm install onsenui vue-onsenui --save

直接ダウンロード

まず、onsenui.jsonsenui.cssonsenui-css-components.css最新の Onsen UI Core から取り出してください。次に、最新の vue-onsenui.jsこちら からダウンロードしてください。

Onsen UI と Vue 2 バインディングの読み込み

Vue 2 バインディングは Vue 2 コンポーネントとディレクティブを提供します。Vue 2 バインディングは Web Components をラップし、Vue 2 ライクな API を提供します。利用するには2つのパッケージを読み込む必要があります:

Onsen UI と Vue 2 バインディングの読み込みには <link><script></script> を使用します:

<link rel="stylesheet" href="onsenui.css">
<link rel="stylesheet" href="onsen-css-components.css">

<script src="vue.js"></script>
<script src="onsenui.js"></script>
<script src="vue-onsenui.js"></script>

また、webpack 等のモジュールバンドラーを使って読み込むこともできます。その場合は、以下のように onsenui パッケージと vue-onsenui パッケージを読み込みます。

// Webpack CSS import
import 'onsenui/css/onsenui.css';
import 'onsenui/css/onsen-css-components.css';

// JS import
import Vue from 'vue';
import 'onsenui';
import VueOnsen from 'vue-onsenui';

Vue.use(VueOnsen);

最後の行で Vue 2 バインディングを Vue プラグインとして読み込んでいることに注意してください(window.Vue が存在する場合は、この作業は自動的に行われます)。 また、ES6 の import の代わりに CommonJS の require を使うこともできます。

Hello World

まずは Hello World アプリを作ってみましょう。以下のサンプルコードは Vue 2 バインディングによる Hello World です。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="onsenui.css">
    <link rel="stylesheet" href="onsen-css-components.css">
    <script src="vue.js"></script>
    <script src="onsenui.js"></script>
    <script src="vue-onsenui.js"></script>
  </head>
  <body>
    <div id="app"></div>
  </body>
  <script>
    var vm = new Vue({
      el: '#app',
      template:
      '<v-ons-page>\
        <v-ons-toolbar>\
          <div class="center"> Title </div>\
        </v-ons-toolbar>\
        <p style="text-align: center">\
          <v-ons-button @click="$notification.alert(\'Hello World!\')">Click</v-ons-button>\
        </p>\
      </v-ons-page>'
    });
  </script>
</html>

このサンプルコードでは vue.jsonsenui.jsvue-onsenui.js の3つの JavaScript ライブラリを読み込んでいます。またスタイルシートについては Onsen UI Core に含まれる onsenui.cssonsen-css-components.css を読み込んでいます。Onsen UI のスタイルシートの詳細については スタイルシートガイド を参照してください。

<link rel="stylesheet" href="path/to/onsenui.css">
<link rel="stylesheet" href="path/to/onsen-css-components.css">

<body></body> タグの中には id 属性に app を指定した <div></div> タグのみを配置します。Vue はその <div></div> の中(Vue コンストラクタの el プロパティで指定した要素の中)にコンテンツを描画します。

α版におけるコンポーネント API

α 版では2つの異なる API を用意しています。 1つ目は Onsen UI Core のものに似た API で、コンポーネントのメソッドを直接呼び出すことによってコンポーネントを操作します。 2つ目は Vue ライクな API で、プロパティとディレクティブによってコンポーネントを操作します。 前者の API は問題なく動作しますが、後者の API は現時点では改善と修正が必要な状況です。α版とβ版では主にそれらの改善と修正を予定しています。 どちらの API も全てのコンポーネントで利用できますが、 混在させないようご注意ください 。 また、どちらの API が好ましいかについてフィードバックをお寄せください

メソッド API

注意: この API は今後のバージョンでプロパティ API に置き換えられる可能性があります。

Vue 2 バインディングで提供している Vue コンポーネントでは、Onsen UI Core が提供しているほとんどのメソッド、属性、プロパティを同じ名前で利用できます(Web Components を直接 Vue インスタンスに変換しているため)。そのためOnsen UI Core のガイドを参照することをお勧めします。

Vue 2 バインディングの Vue コンポーネントが持つメソッドとプロパティにアクセスするには ref および $refs を使用します:

<v-ons-navigator ref="myNavigator">
  <page1 :some-prop="true"></page1>
</v-ons-navigator>
...

$refs.myNavigator.pushPage(pageComponent);

ただし、v-ons-navigatorv-ons-tabbarv-ons-splitter のようなルーティングに関するコンポーネントにアクセスする際は、より簡便な方法があります。Vue 2 バインディングは全ての Vue インスタンスに対して navigatortabbarsplitter の3つの算出プロパティ(computed property)を挿入します。これらの算出プロパティは、this から見て親の位置にある v-ons-navigatorv-ons-tabbarv-ons-splitter を自動的に探索して返します:

const page1 = { // 子ページ
  template: '<v-ons-page>...</v-ons-page>',
  methods: {
    push() {
      this.navigator.pushPage(page2, {data: { something: true }});
      // ここで指定したパラメータは page2 内で this.data.something と書くことで参照できます
    },
    changeTab() {
      this.tabbar.setActiveTab(3);
    },
    openMenu() {
      this.splitter.content.load(page4);
    },
    props: ['someProp']
  }
};

Onsen UI Core ではこれらのメソッドの page 引数には文字列(テンプレート ID)を渡す必要がありました。 しかし Vue 2 バインディングでは v-ons-page を root に持つ Vue インスタンスを直接渡すことができます。

上記の this.navigator.pushPage の例では、遷移先ページ page2data を渡すことで遷移先ページ page2 の Vue インスタンスの this.data を書き換えています。

また、Onsen UI Core と同じく、v-ons-navigatorv-ons-tabbarv-ons-splitter のようなコンポーネントは、page プロパティに Vue インスタンスを渡すことで初期ページを定義することができます。v-ons-navigatorv-ons-tabbarv-ons-splitter の中に要素を挿入する必要はありません。

<v-ons-splitter-side :page="menuPage"></v-ons-splitter-side>

<v-ons-navigator :page="page1" :some-prop="true"></v-ons-navigator>

<v-ons-tabbar :some-prop="true">
  <v-ons-tab :page="page1"></v-ons-tab>
  <v-ons-tab :page="page2"></v-ons-tab>
</v-ons-tabbar>

メソッド API を使うと v-ons-navigator 等のコンポーネントの管理下にあるページにプロパティを渡す(pass down)のが難しくなるため、Vue 2 バインディングでは、各ページに必要なプロパティを親コンポーネントから自動的に引き継ぐ機能を用意しています。例えば上記のコードでは、page1this.someProp === true を親の v-ons-navigator から引き継ぎます。なお、この機能により引き継がれたプロパティはリアクティブではなく、初期値を渡す用途にしか使えないためご注意ください。

プロパティ API - コンポーネント概要

Vue 2 バインディングで提供している Vue コンポーネントでは、Onsen UI Core が提供しているほとんどの属性、プロパティを同じ名前で利用できます(Web Components を直接 Vue インスタンスに変換しているため)。そのためOnsen UI Core のガイドを参照することをお勧めします。

プロパティ API は Vue 2 と高い親和性を持ちます。では、各コンポーネントごとのプロパティ API を1つ1つ見ていきましょう。

Vue 2 はコンポーネントの子の変化を検知して、変化した分だけを更新することができます。この機能により、私達は Navigator の子を操作するだけでページの push、pop を行うことができます:

<template>
  <v-ons-navigator :options="{}">
    <div :is="page" v-for="page in pageStack" :page-stack="pageStack"></div>
  </v-ons-navigator>
</template>
<script>
  import { page1, page2 } from '...';
  export default {
    data() {
      return {
        pageStack: [page1, page2]
      }
    }
  };
</script>

このサンプルコードにおいて、pageStack プロパティを各ページに渡している(pass down)ことに注意してください。pageStack を親コンテキストから操作するメソッドを各ページに渡すというような実装も可能です。さらに良い実装としては、Vuex を使ってページスタックを store するという実装があります。

<template>
  <v-ons-page>
    <v-ons-toolbar>
      <div class="left">
        <v-ons-back-button :on-click="pop">Back</v-ons-back-button>
      </div>
      <div class="center">Title</div>
    </v-ons-toolbar>

    Content
    <v-ons-button @click="push">Push</v-ons-button>
    <v-ons-button @click="replace">Replace</v-ons-button>
  </v-ons-page>
</template>
<script>
  export const page2 = {
    methods: {
      push() {
        this.pageStack.push(page3);
      },
      pop() {
        this.pageStack.pop();
      },
      replace() {
        this.pageStack.pop();
        this.pageStack.push(page3);
        // または this.pageStack.splice(...) など
      }
    },
    props: ['pageStack']
  };
</script>

Vue 2 は pushpopsplice 等による配列の変更を検知します。配列を変更する代わりに新しい配列を代入することでも動作しますが、Vue 2 では親から受け取ったプロパティを書き換えることができないため、実質不可能であることに注意してください。

Navigator は変更を検知し適切なアニメーションを可能な限り実行します。ページスタックを正常に変更するには、各ページが一意な key プロパティを持っている必要があることに注意してください。key プロパティはいくつかのページが変更されなかったことを Vue 2 に伝える役割を持ちます。key プロパティが指定されていないと、Vue 2 は全てのページが変更されたと判断し、全てのページを再生成してしまいます。Navigator の場合、それにより誤ったアニメーションが実行される可能性があります。ページスタックの各インデックスは key プロパティを指定することで初めて安全に変更することができます。例えば、pageStack.shift()pageStack.splice(0, pageStack.length - 2) はトップページを変更しないのでアニメーションが発生しないのが正しい動作ですが、key プロパティが指定されていない場合、トップページが新しいコンポーネントと誤認され、pop アニメーションが発生してしまいます。

Splitter

v-ons-splitter-contentv-ons-splitter-side は、内部のコンポーネントを差し替えることで新しいページを読み込むことができます。また、keep-alive を使用するとコンポーネントをキャッシュすることができます:

<v-ons-splitter>
  <v-ons-splitter-side v-ons-open="sideOpen">
    <menu-page></menu-page>
  </v-ons-splitter-side>

  <v-ons-splitter-content>
    <keep-alive>
      <div :is="pageContent1"></div>
    </keep-alive>
  </v-ons-splitter-content>
</v-ons-splitter>

メニューを開いたり閉じたりするには、v-ons-open というカスタムディレクティブを使用する必要があります。これは v-ons-splitter-side 用の v-model のようなものです。上記のサンプルコードでは、sideOpen に真偽値を代入すると、その値に応じて リアクティブに メニューが開閉します。

Tabbar

Tabbar を利用するには Vue 2 が提供している名前付きスロット(named slot)を使用します。

<v-ons-tabbar v-ons-index="tabbarIndex">
  <template slot="pages">
    <page1></page1>
    <page2></page2>
  </template>

  <v-ons-tab icon="md-home" label="Home"></v-ons-tab>
  <v-ons-tab :icon="iconT2" :label="labelT2"></v-ons-tab>
</v-ons-tabbar>

上記の例では、template 要素内のページコンポーネント2つと v-ons-tab 要素2つがそれぞれ対応しています。v-ons-index カスタムディレクティブを使うと、指定したインデックスのタブをアクティブにすることができます。v-ons-index を使わない場合、v-ons-tabactive 属性を付けることでそのタブを初期のアクティブタブに指定することができます。

また、Vue 2 の機能を活用することで、各ページを遅延生成したり、キャッシュしたりするというような使い方もできます。それを実現するには、以下のようにタブの onClick プロパティを上書きします:

<v-ons-tabbar>
  <template slot="pages">
    <keep-alive>
      <div :is="currentPage"></div>
    </keep-alive>
  </template>

  <v-ons-tab :on-click="() => currentPage = 'home'" :active="currentPage === 'home'"></v-ons-tab>
  <v-ons-tab :on-click="() => currentPage = 'settings'" :active="currentPage === 'settings'"></v-ons-tab>
</v-ons-tabbar>

カルーセルについても、v-ons-index カスタムディレクティブを利用して position を制御することができます。

<v-ons-carousel v-ons-index="carouselIndex" :swipeable="sw" overscrollable>
  <v-ons-carousel-item v-for="item in items"><v-ons-carousel-item>
<v-ons-carousel>

Forms

v-ons-inputv-ons-switchv-ons-rangev-ons-select は対応する Onsen UI Core のコンポーネントと同じように動作します。これらのコンポーネントに対しては v-ons-model カスタムディレクティブを使用します。v-ons-model は、コンポーネントではなくネイティブ要素に対して v-model ディレクティブを使用した時の動作を模倣したものです。

Floating action buttons

v-ons-fab コンポーネントと v-ons-speed-dial コンポーネントは visible プロパティを持っており、このプロパティを操作することで表示状態をトグルすることができます。v-ons-speed-dialvisible プロパティに加えて、アイテムの表示状態をトグルするための open プロパティを持っています。また、クリック時の処理を上書きするには onClick プロパティを使用します(このプロパティを使う際は open プロパティも一緒に使うことをお勧めします)。

<v-ons-speed-dial :visible="isVisible" :open="isOpen" :on-click="isOpen = !isOpen">
  <v-ons-fab :visible="isVisible">+</v-ons-fab>
  <v-ons-speed-dial-item>A</v-ons-speed-dial-item>
  <v-ons-speed-dial-item>B</v-ons-speed-dial-item>
</v-ons-speed-dial>

Dialogs

v-ons-dialogv-ons-alert-dialogv-ons-popoverv-ons-modalvisible プロパティを持ち、このプロパティにより表示状態を操作することができます。バックグラウンドマスク要素を持つコンポーネント(v-ons-modal 以外の全て。v-ons-modal は常にフルスクリーンで表示されるためバックグラウンドマスク要素が存在しません)は、バックグラウンドマスク要素がクリックされると mask イベントを発火します。 バックグラウンドマスク要素がクリックされた時にダイアログをキャンセルするには、Onsen UI Core の cancelable 属性の代わりにこの mask イベントを使用してください。

<v-ons-dialog :visible="dialogVisible" @mask="dialogVisible = false">
  Content here
</v-ons-dialog>

Vue プロトタイプに公開している $notification オブジェクトを使うと、簡単にアラートやプロンプトを出すことができます。Vue.$notification または this.$notification でアクセスできます。動作の内容は Onsen UI Core で提供している ons.notification と全く同じです。

$notification.alert('Hello world!');
$notification.confirm('Do you want to close the app?').then(index => { ... })
$notification.prompt('What\'s your name?').then(input => { ... });

アラートダイアログをカスタマイズしたい場合は v-ons-alert-dialog コンポーネントを使用してください:

<v-ons-alert-dialog modifier="rowfooter"
  :visible="alertVisible"
  @mask="alertVisible = false"
>
  <span slot="title">Title</span>
  Content here
  <template slot="footer">
    <div @click="alertVisible = false">Ok</div>
    <div @click="alertVisible = false">Cancel</div>
  </template>
</v-ons-alert-dialog>

スロットの代わりにプロパティを使うこともできます:

  <v-ons-alert-dialog modifier="rowfooter"
    :title="'Title props'"
    :footer="{Ok: () => alertVisible = false, Cancel: () => alertVisible = false}"
    :visible="alertVisible"
    @mask="alertVisible = false"
  >
    Content here
  </v-ons-alert-dialog>

このコンポーネントを使用するには target プロパティを指定する必要があります。target プロパティには Onsen UI Core でサポートしている任意の値(DOM クエリ, HTML 要素, イベントオブジェクト)に加え、Vue の参照($refs)を指定することもできます。

<v-ons-popover
  :target="$refs.myToolbarButton"
  :options="{}"
  :visible="popoverVisible"
  @mask="popoverVisible = false"
>
  Content here
</v-ons-popover>
<v-ons-modal :visible="modalVisible">
  Content here
</v-ons-modal>
Pull Hook

v-ons-pull-hook は状態変化時にイベントを発火します:

<v-ons-pull-hook
  @action="done => { doSomething(); done(); }"
  @changestate="state = $event.state"
>
  <span v-show="state === 'initial'"> Pull to refresh </span>
  <span v-show="state === 'preaction'"> Release </span>
  <span v-show="state === 'action'"> Loading...  </span>
</v-ons-pull-hook>
条件つき描画

v-if ディレクティブや v-show ディレクティブを使用することで条件つき描画を行うことができます。<v-ons-if platform="android">...</v-ons-if> 等とは書かないようにしてください:

<div v-if="$platform.isAndroid()"> ... </div>
他のコンポーネント

残りのコンポーネントは v-* 接頭辞を持つ以外は Onsen UI Core の要素と同じように動作します。


お困りですか?

Onsen UIに関する質問は、Stack Overflowにてonsen-uiタグを付与してください。Onsen UIチームはあなたの問題解決をお手伝いします。

バグ報告や機能要望については、GitHub Issuesに記載をお願いいたします。

あわせて、下記の情報も参考にしてください。