靈光乍現,lua資料繫結

2022-02-13 07:23:23 字數 2092 閱讀 4923

mvvm的核心就是資料驅動,資料驅動的核心就是資料繫結。

我一直在思考,如何使用lua做乙個資料繫結的功能,仔細思考一下,資料繫結需要做到的功能很簡單,就是當乙個資料改變時,能主動**乙個或多個函式就好了。但是實現起來卻不是那麼簡單。。

這個問題我苦想了幾個月了,也做了幾個版本出來,(**不貼了),但是都不夠完美,主要思路是讀寫資料使用get和set函式,既然是主動呼叫函式,實現**其他函式自然就沒問題了,再簡化一點無非是對每個欄位都可以自動生成get和set函式,但是很明顯,這種方案完全自己使用還行,一旦結合其他庫(哪怕是官方庫),就做不到主動**函式了。(例如官方庫的sort函式,使用「x=123」的形式為x賦值的,並不是呼叫「setx(123)」呀)

所以還需要解決的除了主動**函式外,還得能hook住每次「=」的呼叫。

然後我去思考元表的方案,始終沒能想出乙個好的方案。(智商感人)

而就在今天晚上,真的是靈光乍現啊,是哪位天使大姐被我感動了,來給我指點迷津嗎。

必須寫篇部落格,就當是還願了。

實現方法:

元表的__index和__newindex兩個元方法,會lua的應該都熟悉了,就不囉嗦了。這兩個元方法會在讀寫表中字段的時候觸發,但是觸發這兩個元方法都需要乙個條件:表中不存在某個字段。

接下來就簡單了,只要始終保持表中不存在要繫結的字段就好了。

我tm真是天才。。

話不多說,上**,這是我今晚隨手寫下的**,真正使用的時候再稍微封裝一下就可以了,幾乎完美:

1

local

function

bindable(init)

2local t ={}

3local

mt4 mt =,

67 __index = function

(table, key)

8return

mt[key]

9end,10

11 __newindex = function

(table, key, value)

12local v_old =mt[key]

13if v_old == value then

14return

15end

16 mt[key] =value

17local slots =mt.bind____[key]

18if slots then

19for _, v in

ipairs(slots) do

20v(value, v_old)

21end

22end

23end24}

25setmetatable

(t, mt)

26for k, v in

pairs(init) do

27 t[k] =v

28end

29returnt30

end31

32local

function

bind(table, key, func)

33local binds =table.bind____

34 binds[key] = binds[key] or

{}35

local bind =binds[key]

36 bind[#bind+1] =func

37return #bind

38end

3940

local t =bindable()

4445

local tag = bind(t, "

x", function

(val, old)

46print("

x changed:

", "

new:

", val, "

old:

", old)

47end)48

49 t.x = 250

50 t.x = 100

view code

2016.2.17 更新

我封裝了乙個完整版,放在了

**只有100行,支援各種花式繫結,也支援取消繫結

解決問題與靈光乍現

怎麼去解決乙個非常棘手的問題?這是個極難回答的問題,很難在沒有任何背景的情況下去 我想說的也是不去預設任何背景地去討論它。在給出解決方案的前一步大概率的情況下應該是找到問題的原因,否則便是不斷的試探,窮盡可能的解決策略,這不是本文要討論的方法。那麼如何去找到問題的原因呢?這又是乙個棘手的問題。試探的...

資料繫結 多路繫結MultiBinding

有時候ui要顯示的資訊又不止乙個資料 決定,就需要使用multibinding,multibinding具有乙個名為bindings的屬性,其型別是collection,通過這個屬性multibinding把一組binding物件聚合起來,處在這個集合中的binding物件可以擁有自己的資料校驗與轉...

Spring MVC資料繫結 複雜資料繫結

接上篇spring mvc資料繫結 簡單資料繫結 1 繫結包裝pojo 所謂的包裝pojo,就是在乙個pojo中包含另乙個簡單pojo。例如,在訂單物件中包含使用者物件。這樣在使用時,就可以通過訂單查詢到使用者資訊。1.在po包下新建乙個orderspojo public class orders2...