Improve this

Vue.js

Before reading this section, we suggest you reading Getting Started and Fundamentals to grasp the basics of Onsen UI. Don’t worry, it won’t take more than 5 minutes.

Vue bindings for Onsen UI (VueOnsen) provide Vue 2 components and directives that wrap the core Web Components and expose a Vue-like API to interact with them.

In this guide, we’ll walk you through how to set up Onsen UI + Vue and cover basics to get started.

Download Vue bindings

Vue bindings are distributed in vue-onsenui package. You can download it via NPM:

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

It is also available via CDN. The latest core release contains Vue bindings as well.

Setup Vue bindings

You can load Onsen UI with normal <script></script> and <link> tags as follows:

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

Or you can import VueOnsen from node_modules/vue-onsenui with a module bundler like Webpack:

// 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);

Notice how VueOnsen is used as a plugin for Vue in the last line (this is already done automatically if window.Vue exists). Alternatively, you can use require instead of ES6 imports.

Using Vue CLI

Onsen UI provides ready-to-use templates for Vue CLI as well:

These templates bundle Onsen UI + Vue bindings with unit & e2e testing solutions compatible with Onsen UI.

List of Vue Components

Vue Components

Vue Components API Reference lists up all the Vue Components included in Onsen UI.

Also, Kitchensink app will be useful for determining how components behave. See the code here.

Hello World with Vue

To get started, let’s create a simple Hello World application. The following sample code is a Vue version of Onsen UI HelloWorld.

<!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>

The <div id="app"></div> node is where Vue will render the content into (el property in the constructor).

This is a pure ES5 example, although normally it’s advisable to use ES2015 and vue-loader since it allows *.vue format.

For more information about Vue itself, we recommend reading the official Vue docs.

Understanding Vue Components

Having a general idea about how everything is implemented could be useful in some situations. This is a brief explanation about how Vue Componentes for Onsen UI work.

These components are simple wrappers around inner Custom Elements in most of the cases. This means that a Vue Component takes some props and translate them into DOM properties, DOM attributes or method calls for the Onsen UI core. It also listens for native events and fires the corresponding Vue events. If you inspect the DOM you will likely see a bunch of ons-* components without v-* prefix (these are real HTMLelements). You can have a look at the implementation here.

Since v-ons-* components compiles into ons-* DOM element, you can use this knowledge to style your component with tag names as well.

VOnsPage Compilation

v-ons-page component compiles into ons-page custom element. This element, at the same time, processes its content and filters scrollable and fixed elements. Scrollable content is moved into a special div.page__content wrapper. This behavior might create issues under some specific situations, like using v-for with asynchronous data. To avoid any possible issue, manually providing a div.content element is recommended:

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

  <div class="content">
    <!-- Scrollable content here -->
    <v-ons-input></v-ons-input>
    <div v-for="item in asyncAjaxItems"></div>
  </div>

  <!-- Fixed content here -->
  <v-ons-fab></v-ons-fab>
</v-ons-page>

See also Components Compilation section for more details about this.

The $ons object

The original ons object is not available in the global scope in Vue applications. Instead, it is provided in every Vue instance as this.$ons through Vue’s protoytpe:

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

Event Handling

DOM events fired by Onsen UI elements are translated into Vue events in the corresponding components. For example, v-ons-navigator can handle a postpush event with @postpush="...".

From vue@2.4.0 and vue-onsenui@2.1.0 onwards, native DOM events are passed down to the children. This means that <v-ons-checkbox @change="..."> will work without native modifier. Prior to these versions, @change.native="..." syntax is required. Note that these events are still DOM events and, as such, Vue DevTools won’t show any Vue event for these.

The exception to this is click event, which is turned into a Vue event in some components. The reason is that click event is used to override default behaviors:

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

The previous example overrides the v-ons-back-button default behavior, popping 1 single page, and resets the stack to the first page instead. The prevent modifier is just calling $event.preventDefault().

Additionally, components that are capable of handling Cordova’s backbutton event (Android’s back button), can listen for this event with @deviceBackButton handler.

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

More information about this event in the original Cordova-specific Features section.

Inputs and v-model

Input components in Onsen UI (such as v-ons-input or v-ons-checkbox) support Vue’s v-model directive:

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

The only exceptions are v-model modifiers, which are not supported by custom components as of vue@2.3, unfortunately. However, there is a workaround for the most important one, the lazy modifier:

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

This will update the model on change events instead of input (default). The rest of the modifiers can be easily implemented in other ways.

It is also possible to bind arrays to v-ons-checkbox or v-ons-switch just like normal <input type="checkbox">, and make radio groups with v-model for v-ons-radio.

ES Modules in Vue apps

Apart from vue-onsenui UMD bundle, an ESM version is provided under vue-onsenui/esm since vue-onsenui@2.4.0. This is only useful for development environments that understand ES Modules, i.e. those with a module bundler such as Webpack or Rollup. The main benefit of using this distribution is that non required components will be left out of the bundle without relying on tree shaking algorithms (more information in the main ES Modules section).

import Vue from 'vue';
import VueOnsen from 'vue-onsenui/esm';
import VOnsPage from 'vue-onsenui/esm/components/VOnsPage';
import VOnsToolbar from 'vue-onsenui/esm/components/VOnsToolbar';

Vue.use(VueOnsen);
Vue.component(VOnsPage.name, VOnsPage);
Vue.component(VOnsToolbar.name, VOnsToolbar);

The previous code imports VueOnsen (which is just an alias for $ons object) and registers it in Vue. This step does not include any component at all, unlike import VueOnsen from 'vue-onsenui' would do. Therefore, we can import the necessary components manually and register them as global Vue components (optional). Note that each Onsen UI Vue Component will automatically import its corresponding core Custom Element so there is no need for you to do anything on this regard. Components have a name property that can be used for registering them in Vue (v-ons-page, v-ons-button, etc).

Since importing and registering many components can be very verbose, we recommend creating an extra file with the desired list of components using the following export syntax:

// onsenui-components.js
export { default } from 'vue-onsenui/esm/components/VOnsToolbar';
export { default } from 'vue-onsenui/esm/components/VOnsNavigator';
export { default } from 'vue-onsenui/esm/components/VOnsPage';
export { default } from 'vue-onsenui/esm/components/VOnsCarousel';

Then, simply import and register everything in your main file:

// main.js
import Vue from 'vue';
import VueOnsen from 'vue-onsenui/esm';
import * as OnsenComponents from './onsenui-components.js';

Vue.use(VueOnsen);
Object.values(OnsenComponents).forEach(c => Vue.component(c.name, c));

In case you don’t want to use the default c.name provided, you can assign a new one with export { default as CustomName } from 'vue-onsenui/esm/component/...;' and then using the object key instead of c.name.

Vue Bindings FAQ

How to set up global Onsen UI options?

The main guide describes how to disable or set some global features “right after including onsenui.js in the app”. This means that it must take effect before any component is rendered. Since ons object is not provided globally, we need to use $ons object at the very first possible location:

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
  }
})

This way, changes take effect before any component is rendered.

How to pass data to the next page in the navigator?

Navigator’s pages are sibling elements, which means that communication among them in Vue is fairly challenging. Vuex is a good solution for this, but not the only one. When you push a new page component and want to add some initial data, you can simply extend it:

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

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

In order to send data back to the previous page before popping, any of Vue’s methods for non parent-child communication works.

Can I use Vuex with Onsen UI?

Definitely yes. Vuex is a good solution for components communication. If you have too many props and events up and down, Vuex may be a good fit. For an example of Onsen UI + Vue + Vuex, see kitchensink app.

What about vue-router?

Onsen UI provides its own routing components: v-ons-navigator, v-ons-tabbar and v-ons-splitter. These components can be mixed in many ways to achieve the desired route pattern. This is in general completely enough for mobile SPA, so there is no need to plug an external router.

However, for those who really want to integrate vue-router, it is fully compatible with Onsen UI. It simply has to be integrated with the three routing components mentioned above.