TS+Vue3 模拟 iOS 下的通知中心 NSNotificationCenter 类

499 阅读3分钟

废话开篇:首先说明一点,文章内容没有特别高深的逻辑,仅仅是小白入门理解级别。为什么还要写呢?因为写出来的东西是对自身程序理解程度的一个映射,当然也需要得到更多掘神的指点。那么说明一下主要实现的内容: iOS 下是存在 NSNotificationCenter 类,称之为通知中心,它的最常见的应用情景就是夸层级、跨界面的传值或是事件通知。其实个人理解上来说,Vuex 的应用场景与之类似。

一、实现效果

屏幕录制2022-03-11 上午11.22.39.gif

可以看到,在账号设置->隐私设置 页面里进行了通知的发送,然后在修改密码 页面里注册消息并实现密码输入框的填充。

这里两个界面属于跨级界面,所以,通过注册了全局自定义的通知中心来实现。

注册通知

image.png

发送通知

image.png

二、代码解析

1、定义 Notification 接口类
interface Notification {
  name : string
  object? : any
  callBack? : (object? : any)=>void
}

参数说明:

name:注册消息通知时候的名称。它是响应发送通知的标识。

object:可选类型。消息通知的传入的参数。

callBack:可选类型。回调方法。

2、定义 NotificationCenter 实现类
class NotificationCenter {
notifications! : Notification[]
static Vue : any //全局 Vue对象

constructor(){
   //初始化
   this.notifications = []
}

//获取全局通知中心
static defaultCenter() : NotificationCenter {
   return this.Vue.config.globalProperties.gloabalNotificationCenter
}

//添加通知中心
public addNotification(notification : Notification){
   this.notifications.push(notification)
}

//发送消息
public postNotification(notification : Notification){
   const needOptionNotifications = this.notifications.filter((item)=>{
   return (item.name == notification.name && item.callBack != null)
   })
   //符合通知name的回调全部执行
   needOptionNotifications.forEach((item)=>{
     item.callBack!(notification.object)
    })
   }
}

参数说明:

属性:

notifications:全部保存的通知响应对象。

Vue :静态 Vue 对象。它存在的意义是在纯 ts 模块里通过 vue 里的 getCurrentInstance 方法是拿不到 Vue 对象的,因此,这里强制引用了。

方法:

defaultCenter:获取全局通知中心。

addNotification:添加通知中心。

postNotification:通知中心发送消息。触发符合通知 name 的回调全部执行。

3、VueNotificationCenter
const VueNotificationCenter = {
  install:function(Vue : any){
      const notificationCenter : NotificationCenter = new NotificationCenter()
      Vue.config.globalProperties.gloabalNotificationCenter = notificationCenter;
      NotificationCenter.Vue = Vue;
   }
}

这个对象单纯的就是为 Vue 提供注册 NotificationCenter 用,在 install 实现 NotificationCenter 实例的全局保存,并且把 Vue 对象绑定到 NotificationCenter 类属性上,这样绑定的目的就是可以直接获取 Vue 对象。

main.ts 注册代码

import * as Vue from 'vue'
import VueNotificationCenter from "@/utils/WSLNotification/WSLNotification"

const app = Vue.createApp(App)
app.use(VueNotificationCenter)

4、注册通知中心

修改密码页面代码:

import { ref } from "vue";
import { NotificationCenter } from "@/utils/WSLNotification/WSLNotification";

var content = ref<string>('');
NotificationCenter.defaultCenter().addNotification({
    name:'privacySucceeded',
    callBack(obj? : any){
    alert('我是改密页面:' + JSON.stringify(obj ?? "内容为空"))
    content.value = '123456'
    }
})

这里收到消息通知后,随即简单的修改 contentvalue 值,使页面内输入框默认数据填充。

image.png

5、发送通知

隐私设置页面代码:

import { ref, getCurrentInstance } from "vue";
import { NotificationCenter } from "@/utils/WSLNotification/WSLNotification";

var value = ref<number>(1);
const sureEven = () => {
    NotificationCenter.defaultCenter().postNotification({
        name: "privacySucceeded",
        object: { message: "信息权限更改" },
        });
};

sureEven 为按钮点击事件

image.png

三、注意事项

采用 NotificationCenter 消息通知的 Vue 组件需要设置 keepAlivetrue,将其缓存,使通知中心消息仅注册一次,并且,再收到消息后可进行页面的数据操控。因为,模拟的主要是事件处理而不是数据,那么,页面的缓存处理就变成必要操作了。

设置路由缓存:

image.png

image.png

四、总结与思考

本文仅仅是为熟练 TS 语言而做的模拟操作,并没有什么高深之处,写出来进行总结,代码拙劣,大神勿笑[抱拳][抱拳][抱拳]