# 18.9:全局对象globalThis

globalThis 是 ArkTS 引擎实例内部的一个全局对象,在该引擎实例下所有的 AbilityExtensionAbilityPage 都可以访问并使用它,因此可以通过 globalThis 绑定属性或方法来进行数据同步,以 Stage 模型为例 globalThis 的作用域如下图所示:

18_9_1

# 18.9.1:页面间传值

笔者在第七章第 4 节讲到页面跳转分为页面内跳转和页面间跳转,页面内跳转使用 router,页面间跳转使用 want,它们都可以添加参数,本节笔者演示一下利用 globalThis 实现页面内跳转的参数传递,样例如下:

  • index.ets 页面

    import router from '@ohos.router'
    
    @Entry @Component struct ArkUIClubTest {
    
      @State message: string = "默认值"
    
      build() {
        Column({space: 10}) {
          Text(this.message.toString())
            .fontSize(22)
    
          Button("打开第二页")
            .onClick(() => {
              globalThis.indexParams = { // 给 globalThis 赋予新属性indexParams
                "name": "《ArkUI实战》",
                "site": "www.arkui.club"
              }
              router.pushUrl({           // 打开第二页
                url: "pages/main"
              })
            })
        }
        .width("100%")
        .height("100%")
        .backgroundColor("#aabbcc")
        .padding(10)
      }
    
      onPageShow() {                     // 返回到当前页时,刷新数据
        if (globalThis.indexParams) {
          this.message = JSON.stringify(globalThis.indexParams)
        }
      }
    
    }
    
    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

    index.ets 页面中添加了一个按钮,当点击按钮的时候,给 globalThis 添加了一个 indexParams 属性后并给该属性赋了值,然后页面跳转到 main.ets 页面。

  • main.ets页面

    import router from '@ohos.router';
    @Entry @Component struct Main {
      build() {
        Column() {
          Text(JSON.stringify(globalThis.indexParams)) // 直接使用globalThis.indexParams的值
            .fontSize(22)
            .fontWeight(FontWeight.Bold)
          Button("返回上一页")
            .onClick(() => {
              globalThis.indexParams = {               // 重新给indexParams赋值
                "name": "《ArkUI实战》",
                "site": "www.arkui.club",
                "author": "快乐de灰太狼"                 // 添加的新值
              }
              router.back()                            // 页面返回
            })
        }
        .width('100%')
        .height('100%')
        .backgroundColor("#bbaacc")
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    main.ets 页面里 Text 组件直接使用了在 index.ets 中给 globalThis 添加的 indexParams的值,当点击按钮返回上一页时,重新给 globalThisindexParams 赋予了新值,在返回到 index.ets 后,该页面的 onPageShow() 方法会被调用,然后再该方法里更新了 message 的值,样例运行结果如下图所示:

    18_9_1_1

    📢:onPageShow() 方法属于页面的生命周期方法,有关组件生命周期的讲解,笔者在第九章第 1 节有介绍,不熟悉的读者请自行阅读。

# 18.9.2:全局数据池

globalThis 做为 ArkTS 引擎实例内部的一个全局对象,只要 ArkTS 引擎存在,那么该对象也是一直存在的,因此我们可以对 globalThis 做下包装,把它作为应用的全局数据池来使用,比如应用内有个全局数据管理类 DataManager,它对外提供一个增删改查数据的能力,伪代码实现步骤如下:

  • 定义数据源接口 IDataSource

    // 定义一个数据接口
    interface IDataSource {
      putData(key: string, value: any)
      getData(key: string, defaultValue: any): any
      clear(key: string)
      clearAll()
    }
    
    1
    2
    3
    4
    5
    6
    7

    IDataSource 定义了数据保存、查询和清理操作,具体实现由各实现类来完成。

  • 实现数据源接口 IDataSource

    // 内存缓存实现
    class MemoryDataSourceImpl implements IDataSource {
    
      private mDataEntry: HashMap<string, any> = new HashMap();
    
      putData(key: string, value: any) {
        this.mDataEntry.set(key, value);
      }
    
      getData(key: string, defaultValue: any): any {
        var data = this.mDataEntry.get(key);
        if (data) {
          return data;
        }
        return defaultValue;
      }
    
      clear(key: string) {
        this.mDataEntry.remove(key);
      }
    
      clearAll() {
        this.mDataEntry.clear();
      }
    
    }
    
    // 磁盘缓存实现
    class DiskDataSourceImpl implements IDataSource {
    
      putData(key: string, value: any) {
      }
    
      getData(key: string, defaultValue: any): any {
        return ""
      }
    
      clear(key: string) {
      }
    
      clearAll() {
      }
    }
    
    // 无缓存实现
    class UnCacheDataSourceImpl implements IDataSource {
    
      putData(key: string, value: any) {
      }
    
      getData(key: string, defaultValue: any): any {
        return null
      }
    
      clear(key: string) {
      }
    
      clearAll() {
      }
    }
    
    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
    54
    55
    56
    57
    58
    59
    60

    MemoryDataSourceImplDiskDataSourceImplEmptyDataSourceImpl 都实现了 IDataSource 接口并实现了该接口定义的方法,它们分别把数据存储在内存、磁盘和无缓存

  • 实现数据管理类 DataManager

    export class DataManager {
    
      public static DATA_SOURCE_MEMORY = 0;
      public static DATA_SOURCE_DISK   = 1;
      public static DATA_SOURCE_EMPTY  = 2;
    
      private mDataSourceMap: HashMap<number, IDataSource> = new HashMap();
    
      public constructor() {
        this.mDataSourceMap.set(DataManager.DATA_SOURCE_MEMORY, new MemoryDataSourceImpl());
        this.mDataSourceMap.set(DataManager.DATA_SOURCE_DISK, new DiskDataSourceImpl());
        this.mDataSourceMap.set(DataManager.DATA_SOURCE_EMPTY, new MemoryDataSourceImpl());
      }
    
      public static getDataSource(dataSource: number = DataManager.DATA_SOURCE_MEMORY): IDataSource {
        // 借助globalThis存储DataManager对象sInstance
        if (globalThis.dataManager == null || globalThis.dataManager == undefined) {
          // 借助globalThis存储DataManager对象sInstance
          globalThis.dataManager = new DataManager()
        }
    
        var dataManager = globalThis.dataManager as DataManager;
        var dataSourceImpl = dataManager.mDataSourceMap.get(dataSource)
        if (null == dataSourceImpl) {
          dataSourceImpl = dataManager.mDataSourceMap.get(DataManager.DATA_SOURCE_MEMORY)
        }
    
        return dataSourceImpl
      }
    }
    
    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

    DataManager 默认提供了三种数据缓存实现类,用户可以通过 getDataSource() 方法拿到对应的 IDataSource 实例。

  • 测试样例

    • index.ets 页面

      import router from '@ohos.router'
      
      import { DataManager } from "./../data/DataManager"
      
      @Entry @Component struct ArkUIClubTest {
      
        @State message: string = "默认值"
      
        build() {
          Column({space: 10}) {
            Text(this.message.toString())
              .fontSize(22)
      
            Button("打开第二页")
              .onClick(() => {
                var indexParams = {
                  "name": "《ArkUI实战》",
                  "site": "www.arkui.club"
                }
                DataManager.getDataSource().putData("indexParams", indexParams)
                router.pushUrl({
                  url: "pages/main"
                })
              })
          }
          .width("100%")
          .height("100%")
          .backgroundColor("#aabbcc")
          .padding(10)
        }
      
        onPageShow() {
          this.message = JSON.stringify(DataManager.getDataSource().getData("indexParams", "默认值"))
        }
      }
      
      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
    • main.ets页面

      import router from '@ohos.router';
      import {DataManager} from './../data/DataManager'
      
      @Entry @Component struct Main {
        build() {
          Stack() {
            Column() {
              Text(JSON.stringify(DataManager.getDataSource().getData("indexParams", "{}"))) // 直接从 DataManager 中取值
                .fontSize(22)
                .fontWeight(FontWeight.Bold)
              Button("返回上一页")
                .onClick(() => {
                  DataManager.getDataSource().putData("test", {
                    "name": "《ArkUI实战》",
                    "site": "www.arkui.club",
                    "author": "快乐de灰太狼"                 // 添加的新值
                  })
                  router.back()                            // 页面返回
                })
            }
            .width('100%')
            .height('100%')
            .backgroundColor("#bbaacc")
      
            Image($r("app.media.bg")).enabled(false)
          }
          .width('100%')
          .height('100%')
        }
      }
      
      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

    样例运行结果如下图所示:

    18_9_1_1

    📢:有关 globalThis 的更多介绍,可参考官方文档 (opens new window)

# 18.9.3:小结

本节简单演示了利用 globalThis 全局特性做数据池的用法,需要注意的是在正式应用开发中要防止数据被覆盖的情况出现,最后也非常欢迎小伙伴能给本网站提供更多的开发样例。

(adsbygoogle = window.adsbygoogle || []).push({});
请作者喝杯咖啡

津公网安备 12011402001367号

津ICP备2020008934号-2