local Module = {} local ReactiveWatcherMeta = {} local ReactivePropertyMeta = {} local reactive_watcher_stack = {} local auto_run_watcher_mapping = {} local triggered_watchers = {} -- 由SetProperty激活的watcher列表 local function CreateReactiveWatcher(auto_run) local watcher = rawget(auto_run_watcher_mapping, auto_run) if watcher == nil then watcher = { auto_run = auto_run, properties = {}, } rawset(auto_run_watcher_mapping, auto_run, watcher) setmetatable(watcher, ReactiveWatcherMeta) end return watcher end local function PushWatcher(watcher) table.insert(reactive_watcher_stack, watcher) end local function PeekWatcher() local watcher_stack_deepth = #reactive_watcher_stack if watcher_stack_deepth > 0 then return reactive_watcher_stack[watcher_stack_deepth] else return nil end end local function PopWatcher() local watcher = PeekWatcher() if watcher then table.remove(reactive_watcher_stack) end return watcher end local function AddPropertyToWatcher(watcher, property, key) local properties = watcher.properties local keys = properties[property] or {} keys[key] = true properties[property] = keys end local function ClearAllPropertiesOfWatcher(watcher) local properties = watcher.properties for property, keys in pairs(properties) do local property_watchers = property.watchers for key, state in pairs(keys) do if state == true then local key_watchers = property_watchers[key] key_watchers[watcher] = nil end end end rawset(watcher, "properties", {}) end local function RunFunctionOfWatcher(watcher) local auto_run = watcher.auto_run assert(auto_run ~= nil, "can't find auto run function") ClearAllPropertiesOfWatcher(watcher) -- 解绑所有的binding,由auto_run重新生成 PushWatcher(watcher) auto_run() local poped_watcher = PopWatcher() assert(watcher == poped_watcher, "fatal") end local function GetReactiveProperty(property, key) local meta = property.meta local property_watchers = property.watchers local current_watcher = PeekWatcher() if current_watcher ~= nil then local key_watchers = property_watchers[key] or {} key_watchers[current_watcher] = true property_watchers[key] = key_watchers AddPropertyToWatcher(current_watcher, property, key) end return rawget(meta, key) end local function SetReactiveProperty(property, key, value) local meta = property.meta local property_watchers = property.watchers rawset(meta, key, value) local key_watchers = property_watchers[key] or {} for watcher, state in pairs(key_watchers) do if state == true then triggered_watchers[watcher] = true end end end ReactiveWatcherMeta.__index = ReactiveWatcherMeta ReactivePropertyMeta.__index = GetReactiveProperty ReactivePropertyMeta.__newindex = SetReactiveProperty -- 销毁Reactive Watcher function ReactiveWatcherMeta:Destroy() ClearAllPropertiesOfWatcher(self) auto_run_watcher_mapping[self.auto_run] = nil self.auto_run = nil end function ReactivePropertyMeta:Destroy() local watchers = rawget(self, "watchers") return watchers end -- 创建auto_run的watcher, 并运行auto_run函数 function Module.Watcher(auto_run) local watcher = CreateReactiveWatcher(auto_run) RunFunctionOfWatcher(watcher) return watcher end function Module.ReactiveProperty(data) local Property = { meta = data or {}, watchers = {}, } return setmetatable(Property, ReactivePropertyMeta) end function Module.RawGet(property, key) local meta = rawget(property, "meta") return rawget(meta, key) end function Module.RawSet(property, key, value) local meta = rawget(property, "meta") rawset(meta, key, value) end function Module.Process() local limit = 64 while next(triggered_watchers) and limit > 0 do local triggered_list = {} for w, state in pairs(triggered_watchers) do if state == true then table.insert(triggered_list, w) end end for _, w in ipairs(triggered_list) do limit = limit - 1 triggered_watchers[w] = nil RunFunctionOfWatcher(w) end end end return Module