Created 2018年11月5日15:06
Updated 2018年11月5日15:08
Categories
nodejs
cordova
Teratailで質問した内容と同じですが、こちらにも書いておきます。
Cordova+Vue+Onsen UIでスマホアプリを作っており、メイン画面からv-ons-navigatorで設定画面をpushするような構造にしていました。
設定画面からpopする際にメイン画面に設定を反映させようと試行錯誤したのですが、これがなかなか正しい方法が分からず結構苦労してしまいました。
index.html
<template id="main">
<v-ons-navigator swipeable
:page-stack="pageStack"
@push-page="pageStack.push($event)"
@postpop="testFunction"
></v-ons-navigator>
</template>
<template id="page1">
<v-ons-page>
<v-ons-toolbar>
<div class="center">Page 1</div>
</v-ons-toolbar>
<p style="text-align: center">
This is the first page {{ showText }}
<v-ons-button @click="push">Push Page 2</v-ons-button>
</p>
</v-ons-page>
</template>
<template id="page2">
<v-ons-page>
<v-ons-toolbar>
<div class="left">
<v-ons-back-button>Page 1</v-ons-back-button>
</div>
<div class="center">Page 2</div>
</v-ons-toolbar>
<p style="text-align: center">This is the second page</p>
</v-ons-page>
</template>
<div id="app"></div>
main.js
var page2 = {
key: 'page2',
template: '#page2'
}
var page1 = {
key: 'page1',
template: '#page1',
methods: {
push () {
this.$emit('push-page', page2)
},
changeValue () {
this.showText = 'AAA'
}
},
data () {
return {
showText: 'Not changed'
}
}
}
new Vue({
el: '#app',
template: '#main',
methods: {
testFunction () {
// ここでpage1のchangeValue関数を実行したい
}
},
data () {
return {
pageStack: [page1]
}
}
})
v-ons-navigator
のイベントはどのページからでも呼べるので、page2でv-ons-navigator
のイベントを発火させてpage1の関数を実行する
@postpop
イベントを基軸に#main
コンポーネント内でpage1のchangeValueを呼ぼうとしましたが、
page1.changeValue()
page1.methods.changeValue()
のどっちもダメでした。
理由は恐らくpage1とpage2がただの変数であり、#main
コンポーネント内で使えるようにコンポーネント化されていないからだと思います。
コンポーネント化するにはvueのcomponents
ディレクティブ内に宣言してその宣言通りにHTML内で記述する必要がありますが、v-ons-navigatorはpageStack内のページコンポーネントを自動的に生成するため、親コンポーネントから子コンポーネントに直接アクセスする方法が(調べた限り)見つかりませんでした。
v-bind.sync
でv-ons-navigator
内で共有できる変数を渡す
page1とpage2に直接v-bindを記述できないため参照できませんでした。
ドキュメントを読んでいると、実はv-ons-navigator
のページに書いてありました。
In order to pass data back to the previous page, we can either use Vuex, an event bus, or simply pass a function that modifies the corresponding context.
// Page A
this.$emit('push-page', {
extends: pageB,
onsNavigatorProps: {
passDataBack(data) {
this.dataFromPageB = data;
}
}
});
つまり、上のコードのように$emitのプロパティとして関数を渡してあげれば、page2で実行できるという事でした。
今回のコードの場合、
this.$emit('push-page', {
extends: pageB,
onsNavigatorProps: {
changeValue: this.changeValue
}
})
として、戻るボタンでそれを実行するだけです。つまり、
<v-ons-back-button @click="changeValue">戻る</v-ons-back-button>
これだけでOKでした。なんてあっけない・・・
ちなみに、設定が入っているオブジェクトを直接渡したらPC上のデバッグではうまくいきまいたが、スマホ上ではpage1とpage2で同期が行われずうまくいきませんでした。