Egret社区

坑爹的removeFromStage事件,

2019-10-22 14:51
3426
本帖最后由 Hardy2 于 2019-10-22 15:02 编辑
  1. class SpriteA extends egret.Sprite{
  2.         private sprite:egret.Sprite = new egret.Sprite();
  3.         public constructor() {
  4.                 super();
  5.                 this.addEventListener(egret.Event.REMOVED_FROM_STAGE,this.removeFromStage,this)
  6.                 this.addChild(this.sprite)
  7.         }

  8.         private removeFromStage(e:egret.Event)
  9.         {
  10.                 this.removeAA();
  11.         }

  12.         public removeAA()
  13.         {
  14.                 if(this.sprite)
  15.                 {
  16.                         if(this.sprite.parent)
  17.                                 this.sprite.parent.removeChild(this.sprite);
  18.                         let x:number = this.sprite.x;
  19.                         this.sprite = null;
  20.                 }
  21.         }
  22. }
复制代码
  1. class SpriteB extends egret.Sprite{
  2.         private spriteA:SpriteA = new SpriteA()
  3.         public constructor() {
  4.                 super();
  5.                 this.addChild(this.spriteA);
  6.                 this.addEventListener(egret.Event.REMOVED_FROM_STAGE,this.removeFromStage,this)
  7.         }

  8.         private removeFromStage(e:egret.Event)
  9.         {
  10.                 this.spriteA.removeAA()
  11.                
  12.         }
  13. }
复制代码


然后在Main.ts 里面新建一个SpriteB实例之后,当SpriteB触发了从父对象移除的时候就会获取this.sprite.x的时候报错,根本的原因是事件机制的问题白鹭的事件是
SpriteB 触发REMOVED_FROM_STAGE,执行this.spriteA.removeAA(),在这一次removeAA中触发了this.sprite.parent.removeChild(this.sprite);然后跑到了SpriteA的,removeFromStage,再次执行removeAA(),然后跳出该环,然后再会执行到SpriteB中中的removeAA下的let x:number = this.sprite.x;这一行,

而ActionScript中却不是这样子,as中是SpriteB -》REMOVED_FROM_STAGE -》this.spriteA.removeAA() 本次的整个removeAA跑完才会执行SpriteA 的REMOVED_FROM_STAGE事件,
初步看了一下白鹭的底层,发现原来根本原因是这个DisplayObjectContainer.$EVENT_REMOVE_FROM_STAGE_LIST是静态的

分享到 :
0 人收藏

6 个回复

倒序浏览
Hardy2  登堂入室 | 2019-10-22 16:15:54
顶顶顶,有没人人知道怎么解决啊
wangyq  登堂入室 | 2019-10-22 18:16:24
如果是一次性使用的removeAA里解除事件的监听就好,不是很明白你为什么removeAA要调两次 SpriteB的remove事件只处理自己相关的不行吗 egret也没保证机制要和as完全一样把?你说的解决是解决什么?
bl_h  渐入佳境 | 2019-10-23 09:21:49
Hardy2 发表于 2019-10-22 16:15
顶顶顶,有没人人知道怎么解决啊

你上面那段代码那么写到底是为了什么呢,这么写有什么好处呢
Hardy2  登堂入室 | 2019-10-23 13:17:38
bl_h 发表于 2019-10-23 09:21
你上面那段代码那么写到底是为了什么呢,这么写有什么好处呢

这只是一个例子,这种场景会应用在对象池里,比方说面板移除回池,或者面板数据更新的时候也可以尝试回池
Hardy2  登堂入室 | 2019-10-23 13:47:49
wangyq 发表于 2019-10-22 18:16
如果是一次性使用的removeAA里解除事件的监听就好,不是很明白你为什么removeAA要调两次 SpriteB的remove事 ...

这样子,在SpriteA中加多另外一个方法removeCC,里面移除放在SpriteA中的另外一个显示对象,然后SpriteB中的removeFromStage,removeAA改成removeCC,你会发现,SpriteB中的removeFromStage中的函数还没跑完就执行SpriteA的removeFromStage了,然后你把SpriteB中的内容注释掉removeFromStage,你会发现先跑完SpriteB中的removeFromStage - 》 Sprite 的removeFromStage ,也就是说removeStage中处理移除显示对象会导致子对象的removeFromStage 的顺序可能被提前执行了
wangyq  登堂入室 | 2019-10-24 12:20:33
Hardy2 发表于 2019-10-23 13:47
这样子,在SpriteA中加多另外一个方法removeCC,里面移除放在SpriteA中的另外一个显示对象,然后SpriteB ...

我的疑惑是为什么不能每个sprite的remove事件中只处理自己相关的而非要在一个sprite里再调用另外的一个已经注册过remove事件的sprite的销毁函数呢? 因为我觉得这不是一个非存在不可的逻辑
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号 )

Powered by Discuz! X3.4 © 2001-2019 Comsenz Inc.

返回顶部