Improve this

Vue.js

この章を読み進める前に、Onsen UIをはじめようOnsen UIの基礎に目を通して頂くことを推奨いたします。心配ありません、読み終わるまで5分もかかりません。

Onsen UI向けのVueバインディング(VueOnsen)は、Web Componentsでできたコアをラッピングし、Vue形式のAPIでアクセスできるようにしたものです。

このガイドでは、Onsen UIとVueを組み合わせた場合の開発方法について紹介いたします。

Vueバインディングのダウンロード

Vueバインディングは、vue-onsenuiパッケージとして配布されています。NPMを用いて下記のようにダウンロードできます。

$ npm install onsenui vue-onsenui --save-dev

他にもCDN経由で使ったり、Onsen UIのリリースに含まれているVueバインディングを使うこともできます。

Vueバインディングのセットアップ

Onsen UIを<script></script><link>タグを使って、下記のように読み込めます:

<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を使う場合は、node_modules/vue-onsenuiからVueOnsenインポートしてください:

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

// JS import
import Vue from 'vue';
import VueOnsen from 'vue-onsenui'; // This already imports 'onsenui'

Vue.use(VueOnsen);

Vue.Useを用いてVueOnsenを読み込みます(window.Vueが存在する場合には、これも自動的に行われます)。ES6以降で備わったImport機能を使用しない場合は、requireを用いて読み込むこともできます。

Vue CLIと共に使う

Vue CLIで使えるテンプレートも提供しています:

これらのテンプレートは、Onsen UIとVueを組み合わせたもので、ユニットテストとE2Eテストのための機能も組み込まれています。

Vueコンポーネントの一覧

Vue Components

VueコンポーネントAPIリファレンスではOnsen UIに含まれるすべてのVueコンポーネントが一覧で掲載されています。

また、Kitchensinkアプリをご覧いただくと、それぞれのコンポーネントの挙動を確認することができます。こちらからコードをご確認ください

VueでHello World

では簡単なHello Worldアプリを開発してみましょう。下記のコードは、Onsen UIとVueを用いたHello Worldコードの例になります。

<!DOCTYPE html>
<html lang="en">
<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>
  <template id="main-page">
    <v-ons-page>
      <v-ons-toolbar>
        <div class="center">Title</div>
      </v-ons-toolbar>

      <p style="text-align: center">
        <v-ons-button @click="$ons.notification.alert('Hello World!')">
          Click me!
        </v-ons-button>
      </p>
    </v-ons-page>
  </template>

  <div id="app"></div>

  <script>
    var vm = new Vue({
      el: '#app',
      template: '#main-page'
    });
  </script>
</body>
</html>

ここで<div id="app"></div>は、Vueがコンテンツをレンダリングする起点となります(コンストラクタでelプロパティで指定しています)。

これはES5を用いた例ですが、ES2015とvue-loaderを組み合わせると*.vueファイルを用いた開発ができるのでお勧めです。

Vueに関する詳細は、公式のVueドキュメントを参照してください。

Vueコンポーネント

より深い理解のためにも、Onsen UIとVueコンポーネントの関係について知っておくのが良いでしょう。

これらOnsen UIのVueコンポーネントは、Web ComponentsであるCustom Elementsをラッピングしたものになります。そのため、VueコンポーネントのPropは、Custom ElementsのDOMプロパティや属性、メソッドと対応しています。また、ネイティブイベントを受け取った場合は、Vueイベントを呼び出します。DevTools等でDOMをインスペクトすると、v-*から始まらないons-*コンポーネントが見えるでしょう。これらはWeb Componentsでできた、Onsen UIのHTML要素です。詳細の実装については、こちらのコードを参照してください。

v-ons-*ではじまるコンポーネントは、すべてons-*からはじまるDOM要素にコンパイルされることから、CSS等でスタイルを定義する場合はタグ名を使用してください。

VOnsPageのコンパイル

v-ons-pageコンポーネントはons-pageのカスタム要素にコンパイルされます。この要素はその中に配置された要素を確認し、スクロールされるべき内容と、固定化される内容を判定します。スクロールできる内容はdiv.page__contentラッパーに配置されます。この場合、たとえばv-forにより非同期的にデータを処理するケースなどで問題になることがあります。そのため、下記のように手動でdiv.content要素を追加することを推奨します。

<v-ons-page>
  <v-ons-toolbar></v-ons-toolbar>

  <div class="content">
    <!-- スクロール可能なコンテンツ -->
    <v-ons-input></v-ons-input>
    <div v-for="item in asyncAjaxItems"></div>
  </div>

  <!-- 固定配置するコンテンツ -->
  <v-ons-fab></v-ons-fab>
</v-ons-page>

詳細については、コンポーネントのコンパイルを参照してください。

this.$onsオブジェクト

グローバルで提供されるons objectオブジェクトは、Vueでは利用できません。その代わりに、すべてのVueインスタンスにはthis.$onsオブジェクトを利用できます。

<v-ons-button @click="$ons.notification.alert('Hi there!')">
  Click me
</v-ons-button>

イベント処理

Onsen UI要素で実行されたDOMイベントは、対応するコンポーネントのVueイベントに変換されます。たとえば、v-ons-navigatorpostpushイベントを、@postpush="..."という形で受け取れます。

vue@2.4.0vue-onsenui@2.1.0以降では、ネイティブのDOM要素が子要素に渡されます。そのため、<v-ons-checkbox @change="...">といったイベントはnative修飾子を外しておく必要があります。以前のバージョンでは、@change.native="..."構文が必要でした。ただし、これらは引き続きDOMイベントのため、Vue DevToolsはVueイベントとして認識しません。

ただし、clickイベントについては、いくつかのコンポーネントではVueイベントとして認識されます。これは、デフォルトの挙動が上書きされているためです。

<v-ons-back-button @click.prevent="pageStack.splice(1)"></v-ons-back-button>

この例では、v-ons-back-buttonのデフォルトの振る舞いを変更し、1ページ前に戻った後、先頭ページにリセットを行っています。なお、ここで使われているprevent修正子は$event.preventDefault()を呼び出すために使用しています。

Cordovaのbackbuttonイベント(Androidの戻るボタン)に対応しているコンポーネントについては、@deviceBackButtonハンドラーを使ってイベントを受け取ることができます。

<v-ons-dialog @deviceBackButton="$event.callParentHandler()"></v-ons-dialog>

このイベントに関する詳細は、Cordova特有の機能を使用するを参照してください。

入力とv-modelの使い方

Onsen UIの入力コンポーネント(v-ons-inputv-ons-checkbox)では、Vueが提供するv-modelディレクティブを使用できます。

<v-ons-input v-model="something"></v-ons-input>

ただし、v-model修正子については、Vue 2.3の段階ではカスタムコンポーネントに対して対応されていません。しかし、最も重要なlazy修正子について、下記のように回避することができます。

<v-ons-input v-model="something" model-event="change"></v-ons-input>

この例では、inputイベントの代わりにchangeイベントを用いてモデルの更新を行います。残りの修正子も、同じように実装することができます。

また、v-ons-checkboxv-ons-switchなどのコンポーネントに対して配列をバインドできます。それにより、<input type=“checkbox”>と同じように扱うことができます。また、v-ons-radiov-modelを使ってグループを作成することもできます。

Vueバインディングに関するFAQ

Onsen UIのグローバル設定を変更するには?

ガイドのOnsen UIの一部機能を無効にするに記述されている通り、onsenui.jsを読み込んだ直後に設定を行う必要があります。具体的にはコンポーネントを描画するよりも前に実施される必要があります。しかしVueではonsオブジェクトをグローバルで取得できないため、最初に$onsを受け取れる箇所で設定を行います。

import Vue from 'vue';
import VueOnsen from 'vue-onsenui';
Vue.use(VueOnsen);

new Vue({
  el: '#app',
  render: h => h(...),
  beforeCreate() {
    this.$ons.disableAutoStyling(); // Or any other method
  }
})

このように設定することで、コンポーネントが描画されるよりも先に設定を適用できます。

ナビゲーターに次ページのデータを渡すにはどうすればいいですか?

ナビゲーターのページは、兄弟関係を持つ要素となります。そのため、Vueを用いた場合のデータの受け渡しには工夫が必要です。Vuexを使用する方法だけでなく、下記のように継承を用いてデータを渡すこともできます。

import nextPage from 'nextPage.vue';
// ...

pageStack.push({
  extends: nextPage,
  data() {
    return {
      myCustomDataHere: 42
    };
  }
})

また、ページが戻す際に前ページにデータを渡したい場合は、Vueのドキュメントにある親子関係を伴わないコミュニケーションが参考になるでしょう。

Onsen UIとVuexは組み合わせられますか?

もちろんです。Vuexを使うと、コンポーネント間の通信が書きやすくなります。多くのPropsがあり、イベントが頻繁に発行されるようなケースではVuexを使うのが良いでしょう。Onsen UIとVuexを組み合わせがサンプルは、キッチンシンクアプリを参考にしてみてください。

vue-routerと組み合わせて使うには?

Onsen UIでは、v-ons-navigatorv-ons-tabbarおよびv-ons-splitterを、ルーティング用のコンポーネントとして提供しています。これらを組み合わせることで、必要なパターンのルーティングを実装できます。SPA形式のモバイルアプリ開発においては、これらのコンポーネントだけで足りるケースが多く、追加でルーターを導入する必要はないかもしれません。

もちろん、vue-routerはOnsen UIと完全に互換性があります。上に挙げた3種類のルーティング用コンポーネントと組み合わせてください。