164 lines
4.3 KiB
Lua
164 lines
4.3 KiB
Lua
|
|
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
|