You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua中AppendScript函数优化:避免事件触发时重复追加方法

解决AppendScript重复追加方法的问题

要避免同一个方法被重复追加到UI控件的事件handler中,核心思路是给每个控件维护一个已注册方法的记录集合,每次追加前先检查该方法是否已经存在,存在则跳过追加逻辑。以下是具体实现方案:

方案1:基于函数本身去重(适合具名函数)

修改原有的AppendScript函数,给每个控件实例添加一个_registeredScripts表,用来记录每个事件handler下已添加的方法:

local mt = {
    AppendScript = function(self, handler, method)
        -- 初始化存储已注册方法的结构
        self._registeredScripts = self._registeredScripts or {}
        self._registeredScripts[handler] = self._registeredScripts[handler] or {}
        
        -- 检查方法是否已存在,存在则直接返回
        if self._registeredScripts[handler][method] then
            return
        end
        
        local func = self:GetScript(handler)
        -- 合并原有脚本与新方法
        local newFunc
        if func then
            newFunc = function(...)
                func(...)
                method(...) -- 若不需要传递事件参数,可改为method(),与原逻辑一致
            end
        else
            -- 原有脚本为空时,直接使用新方法
            newFunc = method
        end
        
        self:SetScript(handler, newFunc)
        -- 标记该方法已注册
        self._registeredScripts[handler][method] = true
    end,
}

setmetatable(object, { __index = setmetatable(mt, getmetatable(object)) })

关键点说明

  • _registeredScripts是控件实例独有的表,按事件handler分类存储已添加的方法,利用Lua中函数作为第一类值的特性,直接用method本身作为键来判断重复。
  • 仅当方法未注册时才执行追加逻辑,从根源避免重复绑定。

方案2:自定义唯一标识去重(适合匿名函数)

如果使用匿名函数(每次创建的匿名函数是不同的Lua值,无法用方案1去重),可以给每个待追加的方法指定一个唯一key,通过key来判断重复:

local mt = {
    AppendScript = function(self, handler, key, method)
        -- 兼容不传key的场景,默认用method本身当key
        if not method then
            method = key
            key = method
        end
        
        -- 初始化存储结构
        self._registeredScripts = self._registeredScripts or {}
        self._registeredScripts[handler] = self._registeredScripts[handler] or {}
        
        -- 通过key检查是否已注册
        if self._registeredScripts[handler][key] then
            return
        end
        
        local func = self:GetScript(handler)
        local newFunc = func and function(...)
            func(...)
            method(...)
        end or method
        
        self:SetScript(handler, newFunc)
        -- 标记该key对应的方法已注册
        self._registeredScripts[handler][key] = true
    end,
}

setmetatable(object, { __index = setmetatable(mt, getmetatable(object)) })

使用示例

-- 用自定义字符串作为唯一key,绑定匿名函数
local method = function() 
    -- do stuffs 
end
object:AppendScript("OnShow", "MyUniqueOnShowHandler", method)

这样即使多次调用AppendScript传入相同的key,也只会绑定一次方法。

内容的提问来源于stack exchange,提问作者user3713179

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:03:10