首页 > 解决方案 > addEventListener 指向作为对象属性的函数,加载时不触发函数

问题描述

我正在为朋友制作一个基于文本的、浏览器内的简单 RPG。我想从对象生成菜单元素,并向它们添加事件监听器,以便在单击时激活存储在对象内的相关功能。我有密码——

var inventory = [
	{
		name: "first",
	},
	{
		name: "second",
		use: function(){
			alert	("placeholder function");
		}
	},
	{
		name: "third",
	},
];

function displayInventory(){
	for(i = 0; i < inventory.length; i++){
		document.getElementById("div_name").innerHTML += '<div class="big_div" id="additional_div_' + inventory[i].name + '"> ' + inventory[i].name + ' div';
		if(inventory[i].hasOwnProperty("use")){
			document.getElementById("additional_div_" + inventory[i].name).innerHTML += '<div class="item_use" id="additional_div_use_' + inventory[i].name + '">click here to use item' 
			document.getElementById("additional_div_use_" + inventory[i].name).addEventListener("click", inventory[i].use()); // fires upon loading
			document.getElementById("additional_div_" + inventory[i].name).innerHTML += '</div>'
		}
		document.getElementById("div_name").innerHTML += '</div>'
	}
}


document.onload = displayInventory();
<style>
	.big_div{
		background-color:#ccc;
		margin:10px;
	}
	.item_use{
		cursor:pointer;
	}
<html>
<head>
	<title>GAME</title>
	<meta charset="utf-8">
</head>

<body>
	<div id="div_name"></div>
</body>

</html>

这将在加载时触发旨在使用该项目的功能,而不是在单击时。我知道发生这种情况是因为浏览器在代码中到达函数调用时会读取函数调用,但我无法想出一个也保留生成器样式加载的解决方法。

我需要生成器工作,因为会有大量的项目、地图、敌人等,都以相同的方式加载到菜单中。

我更喜欢在整个过程中使用香草 JS。

标签: javascripthtml

解决方案


您可以为此使用纯 js(forEach 等)。您不需要为此求助于innerHTML。使用createElement代替(如果你想最小化 dom 修改考虑使用new DocumentFragmentorcreateDocumentFragment代替,这里我没有使用它):

https://jsfiddle.net/ibowankenobi/9uo8wuro/

var inventory = [
    {
        name: "first",
    },
    {
        name: "second",
        use: function(){
            alert   ("placeholder function");
        }
    },
    {
        name: "third",
    },
];

var container = document.getElementById("div_name");
inventory.forEach(function(d,i){
   var div = document.createElement("div");
   div.textContent = d.name && d.name || "placeholder";
   div.className = "item_use";
   div.id = "additional_div_use"+i;
   d.use && div.addEventListener("click",d.use,false);
   this.appendChild(div);
},container);

这是基于您想要的更新版本。如果对象有 children 属性,那么它将使用该数组添加元素([ elementType , text , class ]),否则它将使用该name属性添加文本内容:

https://jsfiddle.net/ibowankenobi/9uo8wuro/2/

var inventory = [
    {
        name: "first",
    },
    {
        name: "second",
        use: function(){
            alert   ("placeholder function");
        },
        children:[["div","click here to use item","item_use"]]
    },
    {
        name: "third",
    },
];

var container = document.getElementById("div_name");
inventory.forEach(function(d,i){
   var div = document.createElement("div");
   !d.children && (div.textContent = d.name && d.name || "placeholder");
   div.id = "additional_div_use"+i;
   d.use && div.addEventListener("click",d.use,false);
   d.children && d.children.forEach(function(dd,ii){
       var el = document.createElement(dd[0]);
       el.textContent = dd[1] || "";
       el.className = dd[2] || "";
       this.appendChild(el);
   },div);
   this.appendChild(div);
},container);

推荐阅读