电子预加载中文字字符串中的 Onclick 事件

Onclick event in literal string in Preload for electron

好吧,我需要一些人的帮助,他们知道如何将 innerHTML 中的元素从 foreach 中获取到来自数据库的 table 数据中,我是通过这种方式完成的,但是这不是最优化的方式,所以我需要其他方式的帮助,我添加了一个带有 javascript 的 onclick 事件,我这样做的唯一结果是唯一有效的按钮是 on table 的顶部或 table 的底部按钮。

这是我的工作方式:

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

contextBridge.exposeInMainWorld(
    "electron", {
printmovieonpreload: (results) => ipcRenderer.on("send-movie", (event, results) => {
            mylist.innerHTML = " "
            results.forEach(elements => {
                mylist.innerHTML += `<tr><td> ${elements.movie-name} </td>
                <td> ${elements.movie-duration} min </td><td><button id="btn" value="${elements.id-movie}" "/*this get all the onclick events of the page*/${onclick = deletefromtable}" type="button"  class="fas cli fa-trash-alt"></button></td>
                </tr>`;
            });
        })
});

async function deletefromtable(e) {
/* this is were i filter from id of the onclick event and how i reduce the value of the button to delete it*/
    if (e.srcElement.id == "btn") {
        const obj = {
            id: e.srcElement.value
        }
        await ipcRenderer.invoke('delete_movie', obj);
    }

}

最好不要通过字符串插值来做到这一点,而是让浏览器(用 Electron 的术语,Chromium)创建所需类型的元素,然后设置它们的内容并将它们附加到父级。这可以(并且应该)像这样完成:

// inside your forEach function
var tr = document.createElement ("tr");
var td1 = document.createElement ("td");
var td2 = document.createElement ("td");
var td3 = document.createElement ("td");
var btn = document.createElement ("button");

td1.textContent = elements ["movie-name"];
td2.textContent = elements ["movie-duration"] + " min";

btn.id = "btn";
btn.classList.add ("fas", "cli", "fa-trash-alt");
btn.type = "button";
btn.value = elements ["id-movie"];
btn.onclick = delete_from_table;

td3.appendChild (btn);

tr.appendChild (td1);
tr.appendChild (td2);
tr.appendChild (td3);
myList.appendChild (tr);

但是,要实现此功能,您必须满足以下条件:

  1. elements 数组的索引字符串必须正确。我很确定您使用字符串插值的代码会抛出错误,因为 - 是一个运算符,在使用点运算符引用索引时不能使用。
  2. delete_from_table 必须是函数,而不是字符串。由于它未包含在您发布的代码片段中,因此我无法验证我的解决方案是否可以基于此运行。但是,您似乎更愿意将 updatestatuscero 绑定到按钮的 onclick 事件。如果是这样,只需将 delete_from_table 替换为此函数的名称即可。

关于一般性的更多提示 JavaScript:

  1. 尽可能使用大括号使代码更易于理解。例如,您可以这样编写代码:
contextBridge.exposeInMainWorld(
    "electron", {
        printmovieonpreload: (results) => {
            ipcRenderer.on("send-movie", (event, results) => {
                mylist.innerHTML = " "
                results.forEach(elements => {
                    mylist.innerHTML += `<tr><td> ${elements.movie-name} </td>
                        <td> ${elements.movie-duration} min </td><td><button id="btn" value="${elements.id-movie}" "/*this get all the onclick events of the page*/${onclick = delete_from_table}" type="button"  class="fas cli fa-trash-alt"></button></td>
                        </tr>`;
                });
            });
        }
    }
});

这样一来函数的范围就一目了然了。如果您将代码整理得井井有条,那么您和将来必须使用此代码的任何其他人都会非常高兴。

  1. 使用字符串插值时,可以执行操作。这就是为什么我说 - 在上面的索引中无效。这样做的原因是内插字符串中 ${} 内的任何表达式都将被计算,并且其 return 值将包含在字符串中。因此,
var testObject = {
    "test-prop": "def"
};
var stringA = `abc ${testObject.test-prop} ghi`; // Throws: ReferenceError, prop is not defined
var stringB = `abc ${testObject["test-prop"]} ghi`; // yields "abc def ghi"

stringA 中的表达式试图做的实际上是从 testObject.test 中减去 prop,两者都没有定义。

  1. 此外,通过字符串插值,您执行了一个赋值 (${ onclick = delete_from_table}),这导致定义了新变量 onclick,方法被(正确)写入HTML,但 未绑定到按钮的 onclick 事件 !相反,您可以像 value 属性.

    那样完成 onclick="${delete_from_table}"
  2. 永远不要使用element.innerHTML插入HTML!看看 MDN——这个方法有一些意想不到的含义。最好首先清理您的 HTML,使用 element.insertAdjacentHTML() 或简单地创建元素并使用 element.appendChild() 将它们添加到父元素,如我在上面向您展示的那样。在我看来,这种方式也是最干净的方式,但口味不同。