eletron 12版本以后默认开启了上下文隔离
webPreferences: {
      contextIsolation: true,
}
上下文隔离后, 内存变成了不一样的区域, 通过桥接函数contextBridge.exposeInMainWorld从preload转移过去的都是复制的内容, 桥接过去的obj也是复制的, 在render中修改并不会影响preload. 甚至ipcRender也不能直接桥接过去, .on会丢失.
可是renderer中最重要的就是ipc消息交互了. ipcRenderer.on用不了要如何监听ipcMain发过来的消息?
Eletron官方文档中居然都没有写如何桥接.on,只写了.send和.invoke
参考这个回答吧: https://stackoverflow.com/questions/59993468/electron-contextbridge
两个人给出了两种方式:都是preload.js
第一种:
const {
    contextBridge,
    ipcRenderer
} = require("electron");
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "api", {
        send: (channel, data) => {
            // whitelist channels
            let validChannels = ["toMain"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        receive: (channel, func) => {
            let validChannels = ["fromMain"];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender` 
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        }
    }
);
第二种:
const { ipcRenderer, contextBridge } = require('electron')
const validChannels = ["toMain", "myRenderChannel"];
contextBridge.exposeInMainWorld(
  "api", {
    send: (channel, data) => {
        if (validChannels.includes(channel)) {
            ipcRenderer.send(channel, data);
        }
    },
    on: (channel, callback) => {
      if (validChannels.includes(channel)) {
        // Filtering the event param from ipcRenderer
        const newCallback = (_, data) => callback(data);
        ipcRenderer.on(channel, newCallback);
      }
    },
    once: (channel, callback) => { 
      if (validChannels.includes(channel)) {
        const newCallback = (_, data) => callback(data);
        ipcRenderer.once(channel, newCallback);
      }
    },
    removeListener: (channel, callback) => {
      if (validChannels.includes(channel)) {
        ipcRenderer.removeListener(channel, callback);
      }
    },
    removeAllListeners: (channel) => {
      if (validChannels.includes(channel)) {
        ipcRenderer.removeAllListeners(channel)
      }
    },
  }
);