当前位置: 首页 > 知识库问答 >
问题:

语境桥。在Electron应用程序中使用Typescript显示InMainWorld和IPC:无法读取未定义的属性“send”

吕昀
2023-03-14

我定义了contextBridge(https://www.electronjs.org/docs/all#contextbridge)中。js如下:

const {
  contextBridge,
  ipcRenderer
} = require("electron")

contextBridge.exposeInMainWorld(
  "api", {
      send: (channel, data) => {
          ipcRenderer.invoke(channel, data).catch(e => console.log(e))
      },
      receive: (channel, func) => {
        console.log("preload-receive called. args: ");
        ipcRenderer.on(channel, (event, ...args) => func(...args));
      },
      // https://www.electronjs.org/docs/all#ipcrenderersendtowebcontentsid-channel-args
      electronIpcSendTo: (window_id: string, channel: string, ...arg: any) => {
        ipcRenderer.sendTo(window_id, channel, arg);
      },
      // https://github.com/frederiksen/angular-electron-boilerplate/blob/master/src/preload
/preload.ts
      electronIpcSend: (channel: string, ...arg: any) => {
        ipcRenderer.send(channel, arg);
      },
      electronIpcSendSync: (channel: string, ...arg: any) => {
        return ipcRenderer.sendSync(channel, arg);
      },
      electronIpcOn: (channel: string, listener: (event: any, ...arg: any) => void) => {
        ipcRenderer.on(channel, listener);
      },
      electronIpcOnce: (channel: string, listener: (event: any, ...arg: any) => void) => {
        ipcRenderer.once(channel, listener);
      },
      electronIpcRemoveListener:  (channel: string, listener: (event: any, ...arg: any) => 
void) => {
        ipcRenderer.removeListener(channel, listener);
      },
      electronIpcRemoveAllListeners: (channel: string) => {
        ipcRenderer.removeAllListeners(channel);
      }
  }
)

我定义了一个global.ts:

export {}
declare global {
  interface Window {
    "api": {
      send: (channel: string, ...arg: any) => void;
      receive: (channel: string, func: (event: any, ...arg: any) => void) => void;
      // https://github.com/frederiksen/angular-electron-boilerplate/blob/master/src/preload
/preload.ts
      // https://www.electronjs.org/docs/all#ipcrenderersendtowebcontentsid-channel-args
      electronIpcSendTo: (window_id: string, channel: string, ...arg: any) => void;
      electronIpcSend: (channel: string, ...arg: any) => void;
      electronIpcOn: (channel: string, listener: (event: any, ...arg: any) => void) => void;
      electronIpcSendSync: (channel: string, ...arg: any) => void;
      electronIpcOnce: (channel: string, listener: (event: any, ...arg: any) => void) => 
void;
      electronIpcRemoveListener:  (channel: string, listener: (event: any, ...arg: any) =>
 void) => void;
      electronIpcRemoveAllListeners: (channel: string) => void;
    }
  }
}

在渲染器进程应用程序中。tsx I调用窗口。应用程序编程接口。发送:

window.api.send('open-type-A-window', ''); 

打字稿编译看起来不错:

yarn run dev
yarn run v1.22.5 
$ yarn run tsc && rimraf dist && cross-env NODE_ENV=development webpack --watch --progress 
--color
$ tsc
95% emitting emit(node:18180) [DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning:      
Compilation.assets will be frozen in future, all modifications are deprecated.

BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the 
Compilation.
    Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
    Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.
(Use `node --trace-deprecation ...` to show where the warning was created)
asset main.bundle.js 32.6 KiB [emitted] (name: main) 1 related asset
asset package.json 632 bytes [emitted] [from: package.json] [copied]
cacheable modules 26.2 KiB
  modules by path ./node_modules/electron-squirrel-startup/ 18.7 KiB
    modules by path ./node_modules/electron-squirrel-startup/node_modules/debug/src/*.js 15 
KiB 4 modules
    ./node_modules/electron-squirrel-startup/index.js 1 KiB [built] [code generated]
    ./node_modules/electron-squirrel-startup/node_modules/ms/index.js 2.7 KiB [built] [code 
generated]
  ./src/main/main.ts 6.82 KiB [built] [code generated]
  ./node_modules/file-url/index.js 684 bytes [built] [code generated]
external "path" 42 bytes [built] [code generated]
external "url" 42 bytes [built] [code generated]
external "electron" 42 bytes [built] [code generated]
external "child_process" 42 bytes [built] [code generated]
external "tty" 42 bytes [built] [code generated]
external "util" 42 bytes [built] [code generated]
external "fs" 42 bytes [built] [code generated]
external "net" 42 bytes [built] [code generated]
webpack 5.21.2 compiled successfully in 4313 ms

asset renderer.bundle.js 1000 KiB [emitted] (name: main) 1 related asset
asset index.html 196 bytes [emitted]
runtime modules 937 bytes 4 modules
modules by path ./node_modules/ 990 KiB
  modules by path ./node_modules/scheduler/ 31.8 KiB 4 modules
  modules by path ./node_modules/react/ 70.6 KiB 2 modules
  modules by path ./node_modules/react-dom/ 875 KiB 2 modules
  modules by path ./node_modules/css-loader/dist/runtime/*.js 3.78 KiB 2 modules
  ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 6.67 KiB [built] 
[code generated]
  ./node_modules/object-assign/index.js 2.06 KiB [built] [code generated]
modules by path ./src/ 5 KiB
  modules by path ./src/app/styles/*.less 3.16 KiB
    ./src/app/styles/index.less 385 bytes [built] [code generated]
    ./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/app
/styles/index.less 2.78 KiB [built] [code generated]
  ./src/renderer/renderer.tsx 373 bytes [built] [code generated]
  ./src/app/components/App.tsx 1.48 KiB [built] [code generated]
webpack 5.21.2 compiled successfully in 4039 ms

但我无法读取未定义的属性“send”

如果我在应用程序中设置。tsx:

const sendProxy = window.api.send;

我得到同样的错误,窗口没有呈现:

打字稿和电子IPC有什么问题吗?期待您的帮助

共有2个答案

师成弘
2023-03-14

您是否需要main中的预加载文件。ts?

webPreferences: {
  nodeIntegration: false,
  contextIsolation: true,
  preload: path.resolve(path.join(__dirname, "preload.js"))
},

你必须把这个放在主窗口上。

根据您的webpack配置,可能有一个切入点包,您需要为preload.js文件配置一个额外的webpack输出。

这里有一个示例答案:如何在电子中正确使用preload.js

广楚
2023-03-14

以下是我的设置基于https://www.electronforge.io,它还为公开的api添加了类型。希望它能有所帮助,即使不是一个重点明确的答案。

package.json(使用@electronics-forgepackage.json安装,webpack打字稿模板)中,在entryPoint下,确保您有:

"preload": {
    "js": "./src/preload.ts"
}

在创建BrowserWindow的src/index.ts中,使用神奇的webpack常量来引用捆绑的预加载脚本(也许您的预加载脚本没有捆绑?):

const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY
    }
  });

src/preload的内容。ts:

import { contextBridge } from "electron";
import api from './api'

contextBridge.exposeInMainWorld("api", api);

src/api/index。ts只导出api的所有功能。例子:

import * as myFeature from "./my-feature";

// api exports functions that make up the frontend api, ie that in turn either do IPC calls to main for db communication or use allowed nodejs features like file i/o. 
// Example `my-feature.ts`: 
// export const fetchX = async (): Promise<X[]> => { ... }

export default {
    ...myFeature
}

Types cript 2.9可以通过添加全局声明来识别您的api函数,例如api.fetchX,例如src/index.d.ts(参考):

declare const api: typeof import("./api").default;

...您需要从tsconfig.json中引用:

{ 
  ...
  "files": [
    "src/index.d.ts"
  ]
}

所有这些都完成了,您应该很好地调用api。从渲染器端获取X,并提供键入支持(IDE提供的ymmv),无需导入任何内容。示例App。tsx:

import * as React from 'react'
// do not import api here, it should be globally available

export const App = () => {
  useEffect(() => {
    (async () => {
      const project = await api.fetchX();
      ...
    })();
  }, []);

  return <h1>My App</h1>
}

 类似资料:
  • 问题内容: 除了添加新笔记,一切似乎都可以在这个小应用程序中使用。按钮位于Board组件上。 我知道这个问题通常是由于未正确绑定“ this”的值引起的。我不确定这是否是这里的问题,或者我是否缺少其他东西。谢谢 演示:http://jsbin.com/pewahi/edit?js,输出 问题答案: 您的代码很好。这可能是JSBin的错误,以及如何使用Babel处理转译。如果将杂项添加到代码的顶部,

  • 当我在react中工作时。当我想要侧边页时,我会显示“TypeError:不能读取未定义的属性(读取'pathname')”!

  • 问题内容: 我正在从teamtreehouse.com制作一个非常基本的React应用程序,并且不断遇到 “ TypeError:无法读取未定义的属性’onPlayerScoreChange’” 即使我正确绑定了我的功能(我认为) 是组件中的一种方法,当用户单击“ +”或“-”按钮以更改玩家得分时执行。 如果有人可以解释什么地方出了错,那将非常有帮助,因为我认为我是在曾祖父母的构造函数中进行设置的

  • 为什么我得到这个错误不能读取未定义的触摸属性? 为什么它不能读取,但它可以读取 当我们使用

  • 问题内容: 我正在制作非常简单的react应用。但是,当我尝试通过onChange事件调用父(实际上是祖父母)组件的方法时,我一直在获取。 这是触发事件的组件/表单(因此,在绑定的父组件上调用方法…是的,因为我通过道具将其从父组件传递下来,所以在方法上使用了.bound(this)。) 这是我如何通过大多数父(祖父母)组件中的props传递该方法的方法。 这是我作为父项(方法所有者和方法调用程序之

  • 我正在测试发送电子邮件与流星js和nodemailer插件: 流星添加捷运:流星NodeEmailer 当页面加载时,我在导航器的控制台上看到错误:无法读取未定义的属性“创建运输”。 那么问题是什么呢? 代码如下: /////////////////////////////////////////// ///////////////