はじめに

NativeScript(NativeScript-Vue) の ListView の表示を強制的に更新する方法。

シチュエーションとしては、「お知らせ一覧」のようなものがあって、詳細を確認したら未読アイコンが消える、というような状況。

「お知らせ詳細」から戻るボタンで ListView に戻ってきても、未読アイコンが消えずにかなりハマった。

なお、Android だと上記の問題は起きなかったため、主に iOS 向けの内容。

TL;DR

  • Pageloaded イベントなどにハンドラを設定
  • ハンドラ内で ListView.refresh() を実行する
  • NativeScript-Vue の場合は $refs を使うと楽
この記事が参考になった方
ここここからチャージや購入してくれると嬉しいです(ブログ主へのプレゼントではなく、ご自身へのチャージ)
欲しいもの / Wish list

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. 結論
  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
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.5
BuildVersion: 19F101

$ node -v
v12.7.0

$ npm -v
6.14.5

$ tns --version
6.7.8

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

$ 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 │
└───────────────────────────────┴─────────────────────┘
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 │
└────────────────────────────────────┴─────────┘

詳細

結論

参考: Basics - ListView

Pageloaded イベントハンドラなどで refresh() を使うと OK。

コードのイメージは下記、NativeScript-Vue を使っているので他の Flavor だと分かりづらいかもしれない。
※実際のコードからかなりデフォルメしている(本当は vuexcomputed を使っている)ので、↓のサンプルコードだと問題が起きないかも。

xxxx.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
46
47
48
49
50
51
52
53
<template>
<Page @loaded="onLoaded">
<ListView
for="_news in news"
@itemTap="onNewsTap(_news.id)"
ref="news"
>
<v-template>
<StackLayout>
<Label :text="_news.title" textWrap="true"/>
<StackLayout>
<Label :text="_news.date" />
<Label
text="未読"
:visibility="isRead(_news.id) ? 'collapse' : 'visible'"
/>
</StackLayout>
</StackLayout>
</v-template>
</ListView>
</Page>
</template>

<script >
export default {
data() {
return {
news: [
{ id: 1, title: 'hello', date: '07/01' },
{ id: 2, title: 'bye', date: '07/02' },
],
read_ids: [],
};
},
methods: {
onLoaded() {
// **** これ ****
this.$refs.news.refresh();
},
isRead(id) {
return this.read_ids.includes(id);
},
onNewsTap(id) {
// 既読処理
if (!this.isRead(id)) {
this.read_ids.push(id);
}
// お知らせ詳細に移動
// ...
},
},
}
</script>

ポイントは以下。

  • PageloadedListViewrefresh() を読んでいること
    • こうすると ListView から戻ってきたときも発火する
  • ListViewref="news" を設定していること
    • $refs 経由で this.$refs.news.refresh() のようにメソッドを叩ける

まとめ

  • Pageloaded イベントなどにハンドラを設定
  • ハンドラ内で ListView.refresh() を実行する
  • NativeScript-Vue の場合は $refs を使うと楽

その他・メモ

ここにたどり着くまでにかなり紆余曲折があった(めっちゃハマった)。。。

Vue の watch 使ってみたり、Vuex の getter 使ってみたり、それらと v-ifv-show を組み合わせてみたり、などなど。。。

最終的には公式ドキュメントに載ってたんだけど、NativeScript はググラビリティが低い気がしてしまう。
(たぶん他のメジャーなやつ(ReactNative とか Flutter とか)に比べて、単純に事例が少ないだけなんだろうけど)

参考文献

関連記事

この記事が参考になった方
ここここからチャージや購入してくれると嬉しいです(ブログ主へのプレゼントではなく、ご自身へのチャージ)
欲しいもの / Wish list