require("luaScript.cc.functions") BindableArray = class("BindableArray") function BindableArray:pairs() return pairs(self.Datas) end function BindableArray:ipairs() return ipairs(self.Datas) end function BindableArray:__pairs() return pairs(self.Datas) end function BindableArray:__ipairs() return ipairs(self.Datas) end function BindableArray:len() return self:size(); end function BindableArray:__len() return self:size(); end -- 删除数据 function BindableArray:clear() local datas = self.Datas; self.Datas = {} self.DataCount = 0 for i , v in pairs(datas) do self:raiseEvent("__remove" , i , v); end end -- 排序Datas数据表,当然了,老规矩,排序的表只支持:insert进来的数据,即键是正整数 function BindableArray:sort(func) table.sort(self.Datas , func); end -- 获得元素数量 function BindableArray:size() return self.DataCount end -- 添加元素数量 function BindableArray:insert(value) self[self:size() + 1] = value; end -- 绑定变量属性修改 function BindableArray:bind(name , onChangeFunc) if self[name] == nil then error("找不到成员变量:" .. name) return; end local bindIndex = self:bindEvent(name , onChangeFunc); onChangeFunc(name , self[name]); return bindIndex; end -- 绑定一个事件 function BindableArray:bindEvent(eventName , onAddFunc) if type(onAddFunc) ~= "function" then error("is not a function") return end local name = eventName if self.Binds[name] == nil then self.Binds[name] = {} self.Binds[name]._looping = 0 self.Binds[name].funs = {} end local index = self.BindIndex; -- 如果正在遍历过程中 local bindTable = self.Binds[name] if bindTable._looping > 0 then if self.AddBinds[name] == nil then self.AddBinds[name] = {} end -- 添加到临时列表 self.AddBinds[name][index] = onAddFunc else -- 不在遍历过程中立马加入 bindTable.funs[index] = onAddFunc; end self.BindsByIndex[index] = name; self.BindIndex = self.BindIndex + 1 return index; end -- 解除数据绑定 function BindableArray:unbind(bindIndex) local name = self.BindsByIndex[bindIndex] if name then -- 如果正在遍历过程中 local bindTable = self.Binds[name]; if bindTable._looping > 0 then if self.RemoveBinds[name] == nil then self.RemoveBinds[name] = {} end -- 添加到临时列表 self.RemoveBinds[name][bindIndex] = true else -- 不在遍历过程中立马移除 bindTable.funs[bindIndex] = nil; end self.BindsByIndex[bindIndex] = nil; end end function BindableArray:raiseEvent(eventName , key , value) local bindTable = self.Binds[eventName] if bindTable == nil then return end local funcs = bindTable.funs; if funcs then bindTable._looping = bindTable._looping + 1 -- 这里需要判断回调是否失效 local bindsIndex = self.BindsByIndex for i, v in pairs(funcs) do if bindsIndex[i] then v(key , value); end end bindTable._looping = bindTable._looping - 1 -- 如果在遍历过程中则等执行完 if bindTable._looping > 0 then print("raiseEvent在遍历的过程中,又触发了一次,当前遍历的次数", eventName, bindTable._looping) return end -- 处理新移除 local addBindFunc = self.AddBinds[eventName] local removeBindFunc = self.RemoveBinds[eventName] if removeBindFunc then print("BindableArray:raiseEvent过程中需要删除的绑定事件", table.toString(self.RemoveBinds)) for i, v in pairs(removeBindFunc) do -- 新增列表里面有则也要清掉 if addBindFunc then addBindFunc[i] = nil end funcs[i] = nil end -- 清空临时列表 self.RemoveBinds[eventName] = nil end -- 处理新增加 if addBindFunc then print("BindableArray:raiseEvent过程中需要增加的绑定事件", table.toString(self.AddBinds)) for i, v in pairs(addBindFunc) do funcs[i] = v end -- 清空临时列表 self.AddBinds[eventName] = nil end end end -- 绑定添加元素事件 function BindableArray:bindAdd(onAddFunc) return self:bindEvent("__add" , onAddFunc); end -- 绑定移除元素事件 function BindableArray:bindRemove(onRemoveFunc) return self:bindEvent("__remove" , onRemoveFunc); end -- 绑定更新事件 (update) function BindableArray:bindUpdateTo(onUpdateFunc) return self:bindEvent("__updateTo" , onUpdateFunc); end -- 绑定每一个元素的更新事件 function BindableArray:bindUpdate(onUpdateFunc) return self:bindEvent("__update" , onUpdateFunc); end -- 绑定设置元素事件 function BindableArray:bindSet(onSetFunc) return self:bindEvent("__set" , onSetFunc); end -- 把类数据写入到流 function BindableArray:write(stream) NetStream.writeNetVar(rawget(self , "NetVar") , stream , self); end -- 把类数据发送到服务器 function BindableArray:send(moduleID , commandID, net) if not net then log(debug.traceback()) assert(false); return end local stream = NetStream.new(); self:write(stream); net:send(moduleID , commandID , stream); NetStream.delete(stream); end -- 获取属性回调 function BindableArray:__index(key) local value = self.Datas[key]; if value ~= nil then return value; else local value = BindableArray[key]; if value then return value; else return nil; end end end -- 设置属性回调 function BindableArray:__newindex(key , value) local eventName; local datas = self.Datas; local oldValue = datas[key]; -- 新增 if oldValue == nil and value ~= nil then datas[key] = value self.DataCount = self.DataCount + 1 eventName = "__add" -- 删除 elseif oldValue ~= nil and value == nil then datas[key] = value self.DataCount = self.DataCount - 1 eventName = "__remove" -- 没修改 elseif oldValue == value then return; -- 修改 else datas[key] = value self:raiseEvent(key , key , value); eventName = "__set" end self:raiseEvent(eventName , key , value); -- 总是发生一个__update self:raiseEvent("__update" , key , value); end -- 用以处理数据绑定的更新数据 function BindableArray:updateTo(target) if target == nil or type(target) ~= "table" then return self; end -- 处理新增和修改 for i , v in self:pairs() do local updated = false; if type(v) == "table" then if type(v.updateTo) == "function" then if target[i] ~= nil then target[i] = v:updateTo(target[i]) updated = true; end end end if not updated then target[i] = v; end end -- 处理删除 for i , v in target:pairs() do if self[i] == nil then target[i] = nil; end end target:raiseEvent("__updateTo" , target); return target; end function BindableArray:cloneTo(target) for i , v in self:pairs() do local cloned = false; if type(v) == "table" then if type(v.clone) == "function" then target[i] = v:clone(); cloned = true; end end if not cloned then target[i] = v; end end end -- 深度克隆对象 function BindableArray:clone() local newArray = newBindableArray(); self:cloneTo(newArray); return newArray; end -- 创建一个带数据绑定功能的对象 function _newBindableArray(sourceTable) if type(sourceTable) ~= "table" then print(table.tostring(sourceTable)) end local obj = {} obj.Binds = {} obj.AddBinds = {} obj.RemoveBinds = {} obj.BindsByIndex = {} obj.BindIndex = 0; if sourceTable then obj.Datas = sourceTable local size = 0; for i , v in pairs(sourceTable) do size = size + 1; end obj.DataCount = size; else obj.Datas = {} obj.DataCount = 0; end obj.NetVar = nil; return obj end -- 创建一个带数据绑定功能的对象 local function newBindableArray(sourceTable) local obj = _newBindableArray(sourceTable) setmetatable(obj , BindableArray) return obj end return newBindableArray;