您的位置:首页 > Web前端 > Node.js

【quick遇到的陷阱】node的onExit()和onEnter()

2016-01-14 01:21 756 查看
事情是这样的,我想让继承自node的类能在正确的时刻调用onExit()函数,那我们开始吧。

创建了个空项目,然后MainScene.lua弄成下面的样子,嗯,去掉了label然后在加了几个打印函数。

--MainScene.lua

local MainScene = class("MainScene", function()
return display.newScene("MainScene")
end)
function MainScene:ctor()
printInfo("MainScene:ctor()")
end
function MainScene:onEnter()
printInfo("MainScene:onEnter()")
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
end
return MainScene


我们运行一下,然后退出。log是这样的



合理。我们继续。

新建一个lua文件,myNode.lua,写一个简单的继承自node的节点类。

--myNode.lua

local myNode = class("myNode", function()
return display.newNode()
end)
function myNode:ctor()
printInfo("myNode:ctor()")
end
function myNode:onEnter()
printInfo("myNode:onEnter()")
end
function myNode:onExit()
printInfo("myNode:onExit()")
end
return myNode

然后丢到MainScene里

--MainScene.lua

local myNode = require("myNode")
function MainScene:ctor()
printInfo("MainScene:ctor()")
self.mynode = myNode.new()
:addTo(self)
End
运行,退出。log是这样的。



什么,没看到myNode的onExit和onEnter函数。一开始以为哪里代码写错了,啊,这几行代码也能写错?好吧,先试试手动调用onEnter和onExit。在MainScene.lua里面的onEnter和onExit里分别调用myNode的onEnter和onExit。

--MainScene.lua

function MainScene:onEnter()
printInfo("MainScene:onEnter()")
self.mynode:onEnter()
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
self.mynode:onExit()
end
运行,退出。



结果符合预期。那代码确实没错啊。怎么得要我手动调用呢,这不科学。

嗯,翻开\framework\cocos2dx\NodeEx.lua,找到下面的代码。我们看到了熟悉onXxxx函数,不过都是空的,在下面还有一个函数setNodeEventEnabled
--\framework\cocos2dx\NodeEx.lua

function Node:onEnter()
end
function Node:onExit()
end
function Node:onEnterTransitionFinish()
end
function Node:onExitTransitionStart()
end
function Node:onCleanup()
end
function Node:setNodeEventEnabled(enabled, listener)
if enabled then
if self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end

if not listener then
listener = function(event)
local name = event.name
if name == "enter" then
self:onEnter()
elseif name == "exit" then
self:onExit()
elseif name == "enterTransitionFinish" then
self:onEnterTransitionFinish()
elseif name == "exitTransitionStart" then
self:onExitTransitionStart()
elseif name == "cleanup" then
self:onCleanup()
end
end
end
self.__node_event_handle__ = self:addNodeEventListener(c.NODE_EVENT, listener)
elseif self.__node_event_handle__ then
self:removeNodeEventListener(self.__node_event_handle__)
self.__node_event_handle__ = nil
end
return self
end

简单看看这个setNodeEventEnabled函数,函数主体有两个分支,if和elseif,没有else。注意看第一行if enabled then,所传的参数enabled仅出现在此处,enabled非空时成立,则enabled应该是个bool值,当然语法角度来说,你传任何(not nil)都是ok的。

紧接着这段,移除self的事件监听。

       if self.__node_event_handle__ then

           self:removeNodeEventListener(self.__node_event_handle__)

           self.__node_event_handle__ = nil

       end

你会发现他和elseif分支的代码简直一毛一样

   elseif self.__node_event_handle__ then

       self:removeNodeEventListener(self.__node_event_handle__)

       self.__node_event_handle__ = nil

   end

好了,从结果上来说,不管这个self(node)原本有些什么监听器,那么在调用setNodeEventEnabled之后,这些监听器都say goodbye了。

接着if notlistener then这块。listener应该就是回调函数了。可以看到,当事件名为"enter"时候调用self:onEnter(),当事件名……,原来这些回调默认下是没有被调用的(顺便说,-x里面是会的)。if not listener then之后紧接着。self.__node_event_handle__ =self:addNodeEventListener(c.NODE_EVENT, listener)。就是添加事件监听器了。那么,如果我们自己传入listener的话,就可以只指定的开启某个onXxxx的回调。来试试。

首先,MainScene.lua的onEnter和onExit先删掉myNode的两行。
--MainScene.lua

function MainScene:onEnter()
printInfo("MainScene:onEnter()")
end
function MainScene:onExit()
printInfo("MainScene:onExit()")
end

然后myNode:ctor()中添加代码:

--myNode.lua
function myNode:ctor()
self:setNodeEventEnabled(true, function(event)
if event.name = "enter" then
self:onEnter()
end
end)
printInfo("myNode:ctor()")
end

运行,关掉。看看结果。



Nice

我们试试onExit。替换一下代码我就不完全复制了

--myNode.lua

if event.name = "exit" then
self:onExit()
end



很好。

既然自己传入回调,我们监听指定函数可以么。可以。

写个myNode:myOnExit()函数。

--myNode.lua

function myNode:myOnExit()
printInfo("myNode:myOnExit()")
end
同样的,替换一下代码
--myNode.lua

if event.name = "exit" then
self:myOnExit()
end



设想。在本该onExit的时候却onEnter。

也可以(因为现在这几个函数都仅仅是包涵打印语句,所以并没什么区别。所以实际开发中请三思)

if event.name = "exit" then
self:onEnter()
end



啊。跑题了。

写了那么多,懒癌发作了。我就只是想让节点类正常的回调onExit()罢了。

好,那就只加一行代码。加在:ctor()第一行。或者,不影响监听器添加的某一行下(记住NodeEx.lua里setNodeEventEnabled是会清空节点的当前的事件监听器的)。

function myNode:ctor()
self:setNodeEventEnabled(true)
printInfo("myNode:ctor()")
end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lua cocos2d-x