はじめに

NativeScript-Vue でページ読み込み後にページ移動やダイアログの表示をする方法。

アプリ起動直後のページ(xxxx.vue) 内の createdmounted で、$navigateTo$showModal を使っても期待通りに動作しない場合の対応方法。

TL;DR

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. ページ遷移
    2. モーダル表示
  5. まとめ
  6. その他・メモ
  7. 参考文献

環境・条件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.4
BuildVersion: 19E287

$ node -v
v12.7.0

$ npm -v
6.10.3

$ tns --version
6.4.0

$ grep -C1 version package.json
"tns-android": {
"version": "6.4.1"
},
"tns-ios": {
"version": "6.4.2"
}

$ tns plugin
Dependencies:
┌───────────────────────────────┬─────────┐
│ Plugin │ Version │
│ @nativescript/theme │ ^2.2.1 │
│ @vue/devtools │ ^5.0.6 │
│ nativescript-socketio │ ^3.2.1 │
│ nativescript-toasty │ ^1.3.0 │
│ nativescript-vue │ ^2.4.0 │
│ nativescript-vue-devtools │ ^1.2.0 │
│ tns-core-modules │ ^6.0.0 │
│ vuex │ ^3.1.1 │
└───────────────────────────────┴─────────┘
Dev Dependencies:
┌────────────────────────────────────┬─────────┐
│ Plugin │ Version │
│ @babel/core │ ^7.0.0 │
│ @babel/preset-env │ ^7.0.0 │
│ babel-loader │ ^8.0.2 │
│ nativescript-dev-webpack │ ^1.0.0 │
│ nativescript-vue-template-compiler │ ^2.0.0 │
│ nativescript-worker-loader │ ~0.9.0 │
│ node-sass │ ^4.9.2 │
│ vue-loader │ ^15.4.0 │
└────────────────────────────────────┴─────────┘

詳細

参考: Can’t navigate/open modal/dialog on the ‘mounted’ hook · Issue #555 · nativescript-vue/nativescript-vue

上記参考ページに記載されているが、createdmounted$navigateTo$showModal は期待通りに動作しない。

そのため <Page @loaded="onLoaded"> のように NativeScript 側の loaded イベントに対してハンドラを設定する。

ページ遷移

app/MyPage.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<Frame>
<Page>
<ActionBar :title="title"/>
<StackLayout rows="auto" columns="*">
</StackLayout>
</Page>
</Frame>
</template>

<script >
export default {
props: {
title: {
type: String,
default: 'My Page'
},
},
}
</script>

app/App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<template>
<Page @loaded="loaded">
<StackLayout>
<Label text="App Home"/>
</StackLayout>
</Page>
</template>

<script >
import MyPage from '@/MyPage';

export default {
created() {
// NG: 動作しない
this.$navigateTo(
MyPage,
{ props: { title: 'from created' } }
);
},
mounted() {
// NG: 動作しない
this.$navigateTo(
MyPage,
{ props: { title: 'from mounted' } }
);
},
methods: {
loaded() {
// OK: iOS/Android ともにページ遷移
this.$navigateTo(
MyPage,
{ props: { title: 'from loaded' } }
);
},
},
}
</script>

モーダル表示

自分の環境だと iOS は loaded でも上手く動作しなかったため、さらに setTimeout を組み合わせて対応した。

app/MyModal.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<Frame>
<Page>
<ActionBar :title="title"/>
<GridLayout rows="auto" columns="*">
<Button
text="Close"
@tap="$modal.close()"
row="0"
col="0"
/>
</GridLayout>
</Page>
</Frame>
</template>

<script >
export default {
props: {
title: {
type: String,
default: 'My Modal'
},
},
}
</script>

app/App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<template>
<Page @loaded="loaded">
<StackLayout>
<Label text="App Home"/>
</StackLayout>
</Page>
</template>

<script >
import MyModal from '@/MyModal';

export default {
created() {
// NG: 動作しない
this.$showModal(
MyModal,
{ props: { title: 'from created' } }
);
},
mounted() {
// NG: 動作しない
this.$showModal(
MyModal,
{ props: { title: 'from mounted' } }
);
},
methods: {
loaded() {
// NG: Android では動作したが、iOS では動作しない
this.$showModal(
MyModal,
{ props: { title: 'from loaded' } }
);

// OK: iOS/Android ともにモーダル表示
setTimeout(() => {
this.$showModal(
MyModal,
{ props: { title: 'from timer' } }
);
}, 100);
},
},
}
</script>

まとめ

その他・メモ

NativeScript-Vue 側のマニュアルにも記載が無かったのでしばらくハマった。

参考文献

関連記事