点击这里直接去看源码 >>>

  • 虽然标题是 electron icp 封装(基于vue computed) , 但实际上这套封装可以应用到所有的前后端状态同步场景, 只需要修改一下事件监听与发送的代码。

  • 代码中引入的其他函数的作用

    • env_isRenderer :判断当前代码环境是否处于 renderer , 这个代码前后端都是可以引用的。
    • useElectron :获取 Electron 对象
    • useIpc : 获取 Electron.IpcRenderer 对象
  • 这个封装的作用

    • 无论是在主线程还是渲染线程对该函数产生的计算属性的 set value 都会通过 ipc 同步到主线程与所有的渲染线程
    • 使用起来的时候就无需考虑 .on 这样的代码,就是简简单单的引入一个计算属性然后想咋用咋用。

另外就没什么好说的了,直接去下面看源码吧,注释很详细。

源码

起源项目

import { env_isRenderer } from "../sharedLib";
import { computed, ref, toRaw, UnwrapRef, WritableComputedRef } from "vue";
import { useElectron, useIpc } from "./electron";

export function useIpcComputed<T>(
  channel: string,
  defaultData: T
): WritableComputedRef<UnwrapRef<T>> {

  const { cacheMap, getRendererUpdateChannel } = useIpcComputed;

  if (cacheMap.has(channel)) {

    return cacheMap.get(channel);
  } else {
    const _ref = ref(defaultData);
    const _computed = computed({
      get() {
        return _ref.value;
      },
      set(v: UnwrapRef<T>) {
        _ref.value = v;

        if (env_isRenderer()) {
          // 客户端更新值到服务端,这里会使发送者的 computed 触发两次更新(它自己 set 一次,这里一次),
          // 不过这不是什么大问题,还可以保持各端的数据一致
          useIpc().send(getRendererUpdateChannel(channel), v);
        } else {
          // 服务端推送新值到所有客户端
          useElectron()
            .webContents.getAllWebContents()
            .forEach((webContent) => webContent.send(channel, v));
        }
      },
    });

    if (env_isRenderer()) {
      // 客户端第一次调用 useIpcComputed 从 主线程 更新一下默认值
      useIpc().send(channel);
      // 客户端监听服务端的值更新
      useIpc().on(channel, (event, v: UnwrapRef<T>) => (_ref.value = v));
    } else {
      // 客户端第一次调用 useIpcComputed 会从 主线程 更新一下默认值,这里用于处理该事件

      useElectron().ipcMain.on(channel, (event, v) => {
        // 因为 ref.value 是一个 proxy 而 event.reply 内部无法序列化 proxy
        const _raw_v = toRaw(_ref.value);
        event.reply(channel, _raw_v);
      });
      // 客户端主动更新值
      useElectron().ipcMain.on(
        getRendererUpdateChannel(channel),
        (event, v) => {
          _computed.value = v;
        }
      );
    }

    cacheMap.set(channel, _computed);
    return _computed;
  }
}
export namespace useIpcComputed {

  export const cacheMap = new Map<string, any>();
  export const getRendererUpdateChannel = (s: string) => `${s}-renderer-update`;
}

链接到此文档的相关文档

虽然标题是 electron icp 封装(基于vue computed) , 但实际上这套封装可以应用到所有的前后端状态同步场景, 只需要修改一下事件监听与发送的代码。

electron icp 封装(基于vue computed)

electron icp 封装(基于vue computed)

by 崮生 from 崮生 • 一些随笔 🎨,欢迎 赞助本文
本文欢迎分享与聚合,全文转载未经授权( 联系我)不许可。