本文介绍了Javascript:无法处理多个实例的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为游戏创建组合了一个有趣的 API.在代码中,我为 Mover 创建了一个原型,然后用几个特定的​​原型(Gold、Monster 和 Hero)对其进行扩展.每个都基于具有给定 ID 的 img 标签.我在构造函数中使用特定于类型的信息,并为每种类型使用一个模板方法.Mover 中的大部分功能代码都依赖于那些特定于类型的细节.为简单起见,我包含了一个示例.

I have put together a fun API for game creation. In the code I create a prototype for Mover and then extend it with several specific prototypes (Gold, Monster, and Hero). Each one is based on a img tag with a given ID. I use type-specific information in the constructor and a single template method for each type. Most of the functional code in Mover depends on those type-specific details. I have included one example for simplicity.

我在单独的脚本中使用方法调用来创建和销毁 Mover 子类型的实例.当我一次创建和销毁一个实例时,一切都按预期工作.图像更新,声音播放,并在正确的延迟后被删除.但是,如果我创建两个或更多,则只有最后一个按预期工作.所以,如果我赚了金子,大多数人,英雄.只有英雄会正确移除.另外两个将播放音频,但似乎不会更新.

I use method calls in a separate script to create and destroy instances of the Mover child types. When I create and destroy one instance at a time everything works as intended. The image updates, the sound plays and it is removed after the correct delay. If I create two or more, however, only the last one works as expected. So if I make gold, moster, hero. Only the hero will remove correctly. The other two will play the audio, but don't appear to update.

当我尝试将一个函数附加到多个实例的 onclick 事件时,我遇到了同样的问题.只有最后一个工作,其他人什么也没做.显然,我缺少有关 java 处理方法分配方式的一些信息.您可以提供的任何解释都会有所帮助.谢谢,BSD

I ran into the same problem when I tried to attach a function to the onclick event for more than one instance. Only the last one worked and the others did nothing. Obviously I'm missing something about the way java handles method assignments. Any explanation you can offer would help.Thanks,BSD

function Mover()
{
}

Mover.prototype.InitTag = function()
{
   this.HTMLtag.src=this.imageURL;
   this.HTMLtag.style.position="absolute";
   this.HTMLtag.style.width=characterSize;
   this.HTMLtag.style.height=characterSize;
   this.Position(Math.floor(Math.random()*(MaxW-characterSize)+(characterSize/2)),Math.floor(Math.random()*(MaxH-characterSize)+(characterSize/2)));
}

Mover.prototype.Destroy = function()
{
   var disp = this.HTMLtag.display;
   this.HTMLtag.src=this.destroyURL
   this.HTMLtag.display = disp;
   this.destroyAudio.play();

   this.RemoveTag();
}

function Monster(id)
{
   this.MonsterID = id;
   this.HTMLtag = document.getElementById("monster"+id);
   this.imageURL = "monster1.jpg";
   this.destroyURL = "monster2.jpg";
   this.destroyAudio = monsterAudio;
}

Monster.prototype = new Mover();

Monster.prototype.RemoveTag = function()
{
   var mID = this.MonsterID;
   setTimeout(function() {field.DeleteMonster(mID)}, 1000);
}

function Hero()
{
   this.HTMLtag = document.getElementById("hero");
   this.imageURL = "hero1.jpg";
   this.destroyURL = "hero2.jpg";
   this.destroyAudio = heroAudio;
}

Hero.prototype = new Mover();

Hero.prototype.RemoveTag = function()
{
   setTimeout(function() {field.DeleteHero()}, 5000);
}

function Gold(id)
{
   this.GoldID = id;
   this.HTMLtag = document.getElementById("gold"+id);
   this.imageURL = "gold1.jpg";
   this.destroyURL = "gold2.jpg";
   this.destroyAudio = goldAudio;
}

Gold.prototype = new Mover();

Gold.prototype.RemoveTag = function()
{
   var mID = this.GoldID;
   setTimeout(function() {field.DeleteGold(mID)}, 1000);
}

---------更新更新更新-----------我至少部分解决了这个问题.我已经让它工作了,但我仍然不知道为什么它没有按预期运行.我注意到,虽然我的浏览器 (Chrome) 开发人员工具可以在最近添加的 Mover 被销毁时直观地识别它,但对于任何其他 Mover 却无法这样做.

---------UPDATE UPDATE UPDATE-----------I have at least partially fixed the problem. I have gotten it to work, but I still don't know why it didn't function as intended. I noticed that while my browser's (Chrome) developer tools could visually identify the most-recently-added Mover when it was being destroyed, it could not do so with the any other movers.

可以在 Chrome 开发者工具中识别最近添加的 Mover 的标签.这表明 Mover.HTMLtag 实际上与 document.getElementById('mover1') 不同.我能够通过查看 GoldField.DeleteMover 中的变量来确认这一点.在表示 mover.src 未更改的行,但 movers[id].HTMLtag.src 已正确更新.在最近添加的情况下,它们都是相同的.

Tag of most recently added Mover can be identified in Chrome developer tools.This suggested that Mover.HTMLtag was not actually the same as document.getElementById('mover1'). I was able to confirm this by looking at the variables in the GoldField.DeleteMover. At the line indicated mover.src has not changed, but movers[id].HTMLtag.src has been correctly updated. In the most-recently-added case they were both the same.

GoldField.prototype.DeleteMover = function(id)
{
  var isHero = false;
  if(this.Hero!=null && id==this.Hero.myID)
  {
    this.Hero = null;
    isHero = true;

  }
  else if(this.Tower!=null && id==this.Tower.myID)
  {
    this.Tower = null;
  }

  var mover = document.getElementById("mover"+id);
  if(!isHero)
  {
    this.tag.removeChild(mover);//<<< HERE HERE HERE HERE
    delete this.movers[id];
  }
}

所以,我在 Mover.Destroy 中更改了一行.通过 ID 查找标签并设置 src.我能够可靠的行为.添加第二个 Mover 后,Mover.HTMLtag 似乎不再可靠.有什么解释吗?

So, I changed one line in Mover.Destroy. By finding the tag by ID and setting the src. I was able to reliable behavior. It would appear that Mover.HTMLtag is not reliable the same after the second Mover is added. Any explanation?

Mover.prototype.Destroy = function()
{
   document.getElementById(this.HTMLtag.id).src=this.destroyURL;
   this.HTMLtag.src=this.destroyURL;//old method
   this.destroyAudio.play();

   this.RemoveTag();
}

怀疑这可能会扩展到 this.HTMLtag 的其他更新,我设置了 Hero 的一些基本动作.它工作得很好,但是如果您添加任何类型的额外移动器,它就不再移动.这大大缩小了问题的范围.为什么构建第二个 Mover 会导致原型成员发生变化?

On suspicion that this might extend to other updates to this.HTMLtag I set up some basic movement of the Hero. It works great, but if you add one additional Mover of any kind it no longer moves. That narrows down the question considerably. Why would constructing a second Mover cause the prototype members to change?

推荐答案

所以我调试了你的代码并找到了你的问题的原因.问题是当你创建一个新的怪物实例时,你在怪物 var 上存储了一个对它的引用.当您删除它时,您不会删除/更新对它的引用.所以你的删除函数 myField.DeleteMover(id) 尝试删除一个已经删除的怪物.如何解决这个问题.

So I debug your code and I found the cause of your problem. The problem was when you create a new instance of monster you storing a reference to it on the monster var. And when you delete it you don't delete / update the reference to it. So your delete function myField.DeleteMover(id) try to delete a monster already deleted. How to solve this.

// create an array to keep ref to our instances
var monsters= [];
// var monster = null;
function addMonster()
{
  // monster = goldField.AddMonster();⏎
  // push every monster in array
  monsters.push(goldField.AddMonster());
}

function killMonster()
{
  // if array.length is true
  if (monsters.length) {
    // call the destroy function on the last ref
    monsters[monsters.length - 1].Destroy();
    // remove the last ref from array using pop
    monsters.pop();
  }
//monster.Destroy();
}

这是有效的,但是我认为所有这些都应该在对象本身中完成.你不应该在这里关心它.

This is working however I think all of this should be done in the objects itself. And you should not care about it here.

另一个建议尝试使用更多数组方法.避免在数组索引上使用删除,因为它会混淆索引和计数,而是使用 splice(index, 1) 相同,用于在数组中添加项目使用推送而不是任意索引.

Another advice try to use more array methods. Avoid using delete on array index because it mess with index and count instead use splice(index, 1) same for add item in array use push instead of arbitrary index.

无论如何有趣的游戏!祝你顺利完成.

Anyway funny game! Good luck to finish it.

编辑,在你回答后我回去测试.为了让它发挥作用,我这样做.

Edit, after your answer I go back an test.To make it work I do this.

// First go inGoldField.prototype.DeleteMover and replace the ugly delete index by
this.movers.splice(id, 1);
// Then in the Mover.prototype.Destroy
// This part is a a little blurred for me.
// the current HTMLtag looks good but when I console.log like this
console.log('before', this.HTMLtag);
this.HTMLtag = document.querySelector("#mover" + this.myID);
console.log('after', this.HTMLtag);
// They are not equal look like the first is outdated

您应该将所有删除和添加转换为拼接和推送方法.
这只是一个快速调试我不知道为什么选择器已经过时了.

You should convert all your delete and add to splice and push methods.
This is just a quick debug I don't know why the selector is outdated.

这篇关于Javascript:无法处理多个实例的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-22 08:00