2017/02/16時点でのOnsenUI+VueJSでタブ＋ナビゲーションをやってみる

タイトル通りですが、2017/02/16時点でのもの(=vue-onsenuiはアルファバージョン)なので、多分治る・・・と思いますが、自身へのメモも含めて記載。

まずは全ソース

```
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data:; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    
    <!-- -->
    <script src="js/vue-onsenui.js"></script>
    <script>
    var db = window.openDatabase("database", "1.0", "testdatabase", 1000000);
    </script>
</head>
<body>

<!-- Vueで呼び出されるテンプレート -->
<template id="main">
  <v-ons-navigator>
    <div :is="page" v-for="page in pageStack" :page-stack="pageStack"></div>
  </v-ons-navigator>
</template>

<!-- タブ -->
<template id="tab">
  <v-ons-page>
    <v-ons-toolbar>
      <div class="center">{{ title }}</div>
    </v-ons-toolbar>
  
    <v-ons-tabbar v-ons-index="activeIndex" position="auto" :visible="true">
      <template slot="pages">
        <home-page></home-page>
        <news-page></news-page>
        <settings-page></settings-page>
      </template>
  
      <v-ons-tab v-for="tab in tabs"
        :icon="!$platform.isAndroid() && tab.icon"
        :label="tab.label"
        :badge="tab.badge"
      ></v-ons-tab>
    </v-ons-tabbar>  
  </v-ons-page>
</template>

<!-- カスタムツールバー -->
<template id="custom-toolbar">
  <v-ons-toolbar>
    <div class="left">
      <v-ons-back-button :on-click="pop">{{ backLabel }}</v-ons-back-button>
    </div>
    <div class="center"><slot></slot></div>
  </v-ons-toolbar>
</template>

<!-- スタック -->
<template id="home">
  <v-ons-page>
    <custom-toolbar :pop="pop">Page 1</custom-toolbar>
    <p style="text-align: center">
      This is the first page
      <v-ons-button @click="push">Push Page 2</v-ons-button>
    </p>
  </v-ons-page>
</template>

<template id="page2">
  <v-ons-page>
    <custom-toolbar :pop="pop" :back-label="'Page 1'">Page 2</custom-toolbar>
    <p style="text-align: center">This is the second page</p>
  </v-ons-page>
</template>

<template id="news">
  <v-ons-page>
    <p style="text-align: center">
      Some news here.
    </p>
  </v-ons-page>
</template>

<template id="settings">
  <v-ons-page>
    <p style="text-align: center">
      Change the settings.
    </p>
  </v-ons-page>
</template>

<!-- 定義 -->
<div id="app"></div>

</body>

<script>

var gPageStack = [];

// ページ転移スタック
const pop = function() {
  gPageStack.pop();
};

// 表示のためだけのワークページ
const newsPage = {
  template: '#news'
};

// 表示のためだけのワークページ
const settingsPage = {
  template: '#settings'
};

// カスタムツールバー表示テンプレート用データ
const customToolbar = {
  template: '#custom-toolbar',
  props: ['pop', 'backLabel']
};

const page2 = {
  template: '#page2',
  methods: { pop },
  props: ['pageStack'],
  components: { customToolbar }
};

const homePage = {
  template: '#home',
  methods: {
    pop,
    push() {
      gPageStack.push(page2);
    }
  },
  components: { customToolbar }
};

// タブ表示テンプレート用データ
const tabPage = {
  template: '#tab',
  data() {
    return {
      activeIndex: 0,
      tabs: [
        {
          icon: 'ion-home',
          label: 'Home'
        },
        {
          icon: 'ion-ios-bell',
          label: 'News',
          badge: 7
        },
        {
          icon: 'ion-ios-settings',
          label: 'Settings'
        }
      ],
    };
  },
  computed: {
    title() {
      return this.tabs[this.activeIndex].label;
    }
  },
  props: ['pageStack'],
  components: { homePage, newsPage, settingsPage }
};

gPageStack.push(tabPage);

// Vueクラス
new Vue({
  el: '#app',
  template: '#main',
  data () {
    return {
      pageStack: gPageStack
    };
  }
});

</script>

</html>
```

ポイントはタブで使用するコンポーネント(homePageとnewsPageとsettingsPage)において
props
を定義しないことです(定義すると空配列だろうがエラーになります)

そのため、スタック用配列をグローバル定義してそれを利用することで回避して動作するようにしてます。

バグっぽい気がするけど、どうなんだろう・・・・