You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加keyCode事件逻辑后Electron sendPin方法调用报错

问题现象

Electron 项目中 sendPin 函数调用失败,控制台抛出如下错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'sendPin')
    at HTMLDocument.handlekeyUp (pin-pad:86:28)
pin-pad:61 Uncaught TypeError: Cannot read properties of undefined (reading 'sendPin')
    at HTMLDivElement.<anonymous> (pin-pad:61:28)

添加键盘回车触发提交的代码前,点击页面上的Enter按钮提交PIN的功能完全正常,异常是在加入以下代码段后出现的:

if (13 === e.keyCode) { window.electronAPI.sendPin(Pin);

相关项目代码

index.html(PIN输入页面)

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="pinpad.css" />

    <meta charset="UTF-8" />
    <title>Electron Test - Pin Pad</title>
    <meta
      http-equiv="Content-Security-Policy"
      content="script-src 'self' 'unsafe-inline';"
    />
  </head>

  <body>
    <div id="container">
      <div id="wrapper">
        <input type="password" id="display" disabled />

        <div id="pin-pad">
          <div data-number="1">1</div>
          <div data-number="2">2</div>
          <div data-number="3">3</div>
          <div data-number="4">4</div>
          <div data-number="5">5</div>
          <div data-number="6">6</div>
          <div data-number="7">7</div>
          <div data-number="8">8</div>
          <div data-number="9">9</div>
          <div>Enter</div>
          <div data-number="0">0</div>
          <div>Clear</div>
        </div>
      </div>
    </div>
  </body>

  <script>
    let display = document.getElementById("display");
    let validKeys = [
      "1",
      "2",
      "3",
      "4",
      "5",
      "6",
      "7",
      "8",
      "9",
      "0",
      "Enter",
      "Clear",
    ];
    let pin = "";

    document.getElementById("pin-pad").addEventListener("click", (event) => {
      if (!validKeys.includes(event.target.innerText)) {
        return;
      }

      if (event.target.innerText === "Enter") {
        window.electronAPI.sendPin(pin);
        return;
      }

      if (event.target.innerText === "Clear") {
        pin = display.value = "";
        return;
      }

      pin = pin + event.target.innerText;
      display.value = "*".repeat(pin.length);
    });

    ///tests
    const handlekeyUp = function (e) {
      e.stopPropagation();

      const input = document.getElementById("display");
      console.log(input, e.key, input.value);
      var reg = new RegExp("^[0-9]$");
      const number = document.querySelector(`[data-number="${e.key}"]`);

      if (reg.test(e.key)) input.value += e.key;
      if (number) number.style.backgroundColor = "#fff";
      if (13 === e.keyCode) {
        window.electronAPI.sendPin(Pin);
      }
    };

    const handleKeyDown = (e) => {
      const number = document.querySelector(`[data-number="${e.key}"]`);
      if (!number) {
        return;
      }
      number.style.backgroundColor = "#eee";
    };

    document.addEventListener("keyup", handlekeyUp);

    document.addEventListener("keydown", handleKeyDown);
  </script>
</html>

main.js(主进程代码)

const electronApp = require("electron").app;
const electronBrowserWindow = require("electron").BrowserWindow;
const electronIpcMain = require("electron").ipcMain;

const nodePath = require("path");

// Prevent garbage collection
let window;

function createWindow() {
  const window = new electronBrowserWindow({
    fullscreen: true,
    show: false,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: nodePath.join(__dirname, "preload.js"),
    },
  });

  window.loadFile("pin-pad.html").then(() => {
    window.show();
  });

  return window;
}

electronApp.on("ready", () => {
  window = createWindow();
});

electronApp.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    electronApp.quit();
  }
});

electronApp.on("activate", () => {
  if (electronBrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// ---

electronIpcMain.on("pin", (event, pin) => {
  // Simple check of pin validity
  if (pin === "1234") {
    window.loadFile("sales.html");
  }
});

preload.js(预加载脚本)

const contextBridge = require("electron").contextBridge;
const ipcRenderer = require("electron").ipcRenderer;

contextBridge.exposeInMainWorld("electronAPI", {
  sendPin: (pin) => {
    ipcRenderer.send("pin", pin);
  },
});

问题原因与修复方案

代码里有3个明确问题,按影响优先级排序:

  1. 变量名大小写错误
    全局存储输入PIN的变量是小写开头的pin,但键盘回车事件中传入的是大写开头的Pin。JavaScript大小写敏感,未声明的Pin变量会触发执行错误,打断上下文逻辑,连原有正常的点击提交逻辑也会受连带影响。
    修复:将window.electronAPI.sendPin(Pin)改为window.electronAPI.sendPin(pin)。

  2. 键盘输入逻辑不同步
    handlekeyUp函数中,按下数字键时仅修改了输入框的显示值,没有同步更新全局pin变量,即使修复大小写问题,键盘输入的密码内容也不会被正确提交。
    修复:将数字键处理逻辑修改为:

    if (reg.test(e.key)) {
      pin += e.key;
      input.value = "*".repeat(pin.length);
    }
    

    同时补充键盘按Clear/退格键的清空逻辑,和点击交互保持一致。

  3. 页面文件名不匹配
    主进程createWindow中加载的页面是pin-pad.html,但提供的页面代码文件名为index.html,如果实际运行时两个文件内容不同步,比如pin-pad.html未同步最新代码,也会触发electronAPI undefined的错误。
    修复:确认主进程加载的HTML文件和修改的代码文件是同一个,避免改了A文件但程序加载B文件的问题。

另外贴出的异常代码段末尾缺少闭合大括号},如果实际代码中漏写会直接触发JS语法错误,导致整个页面脚本执行失败,补全大括号即可。


内容的提问来源于stack exchange,提问作者erhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:21:38