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 |