问题描述
我正在使用模板文字将内容插入页面:
entries.forEach((entry) => {
let id = entry.id;
entryList.innerHTML += `
<div class="entry">
<button class="delete-btn" onclick="deleteEntry(${id})">D</button>
</div>`;
});
当我单击按钮时,我收到“未捕获的SyntaxError:无效或意外的令牌”。
但是,如果我改按按钮:
<button class="delete-btn" onclick="deleteEntry(3)">D</button>
该错误不会发生。
您能告诉我这里怎么了吗?谢谢。
解决方法
您的id
值必须用引号引起来。您已经说过:
生成的HTML正是我想要的:
<button class="delete-btn" onclick="deleteEntry(e5f7ce9a-1383-5d7c-9a9b-e8ce73d09041)">D</button>
但是在属性中查看该代码:
deleteEntry(e5f7ce9a-1383-5d7c-9a9b-e8ce73d09041)
这是语法错误。该字符串必须用引号引起来。
最小的更改是在'
周围添加${id}
,假设您知道'
永远不会出现在id
值中:
entries.forEach((entry) => {
let id = entry.id;
entryList.innerHTML += `
<div class="entry">
<button class="delete-btn" onclick="deleteEntry('${id})'">D</button>
</div>`;
...但是正如我在评论中所说,将+=
与innerHTML
一起使用,以及使用onxyz
-属性样式的事件处理程序通常都是不好的主意:
- 执行
element.innerHTML += "some string"
时,浏览器必须遍历element
中的整个DOM结构,并构建HTML字符串以传递给您的JavaScript代码。然后,您的JavaScript代码必须追加到字符串,并将其返回给浏览器。然后,浏览器必须完全删除element
的所有内容,解析JavaScript代码给它的字符串,并为曾经存在的元素(然后再为新元素)构建新元素。这是很多不必要的工作,而且是有损失的:事件处理程序丢失,用户的聚焦元素(如果位于element
中)丢失,并且表单元素中的当前选择丢失。相反,请考虑createElement
,appendChild
,insertBefore
,insertAdjacentHTML
,insertAdjacenText`和其他各种DOM方法。 -
onxyz
属性类型的事件处理程序要求您发出语法有效的代码并对其进行编码,以使其可以正确显示在属性中,并且只能使用全局函数。通常,最好避免使用全局功能。而是考虑使用现代事件处理,addEventListener
等。这样也可以避免导致问题的问题(不输出语法有效的代码)。
例如:
entries.forEach(({id}) => {
entryList.insertAdjacentHTML(
"beforeend",`<div class="entry">
<button class="delete-btn">D</button>
</div>`
);
entryList.lastElementChild.querySelector("button").addEventListener(
"click",() => deleteEntry(id)
);
// ...
这是我在那里做的:
- 我在参数列表中使用了结构分解,只挑选了对象的
id
属性,以使代码不会覆盖对象引用。 - 我使用
insertAdjacentHTML
将DOM结构添加到entryList
的末尾,而没有销毁并重新创建所有先前的元素。 - 我在新元素(
querySelector
)上使用了entryList.lastElementChild
来获取按钮,并使用了addEventListener
为其添加了事件处理程序。这样可以避免将id
的值用引号引起来的麻烦,并且可以根据需要使deleteEntry
为非全局值。
这是工作示例:
const entries = [{id: 1,text:'Hello World!'},{id: 2,text:'ABC'},{id: 3,text:'XYZ'}];
const entryList = document.querySelector('#entryList');
deleteEntry = function(id) {
console.log('clicked id : ',id);
}
entries.forEach((entry) => {
let id = entry.id;
entryList.innerHTML += `
<div class="entry">
<button class="delete-btn" onclick="deleteEntry(${id})">D${id}</button>
</div>`;
});
<div id="entryList"></div>
,
对于字符串文字,您必须使用引号
onclick=`deleteEntry(${id})`