数据节点 (Data Node) 入门

GDVM的核心是构建VM,并建立VM与自定义的Model和View之间的关系, 而 数据节点(Data Node) 就是构建VM的组件。

所有数据节点都继承自 DataNode

数据节点是一组封装好的数据结构,主要分为6种类型:

变体型(Variant)

DataNodeVariant

变体型包含一个Variant空间,如果是基础数据类型则保存的是其本身,如果是对象、字典、数组类则保存的是其引用。

Godot的Variant能保存什么,DataNodeVariant就能保存什么。

var a := Gdvm.DataNodeVariant.new("hello world")

构造函数代入的值就是其初始值。

如果不需要跟踪内容的变化,变体型也可以保存对象、字典和数组。

严格型(Strict)

DataNode[Type]

一个Variant的存储空间是20字节,对于大多数基础数据类型并无必要。

所以对于基础数据类型,应该用类型对应的严格型DataNode保存。

严格型只支持基础数据类型,而不支持对象、字典、数组类型。

严格型的DataNode即 DataNode[类型],如: DataNodeInt DataNodeVector2 等。

所有严格型都继承自 DataNodeStrict

var a := Gdvm.DataNodeInt.new(100)

列表型(List)

DataNodeList

如果需要跟踪列表元素的变化,可以使用 DataNodeList

``DataNodeList``的元素也是DataNode,每个元素都跟踪其变化。

创建DataNodeList需要显式指定元素的类型( GDVM风格的 ),以及一个元素DataNode的工厂函数。

var a := Gdvm.DataNodeList.new(TYPE_INT, func():
  return Gdvm.DataNodeInt.new(0)
)

字典型(Dict)

DataNodeDict

如果需要跟踪字典元素的变化,可以使用 DataNodeDict

``DataNodeDict``的元素也是DataNode,每个元素都跟踪其变化。

创建DataNodeDict需要显式指定键的类型、值的类型,以及一个值DataNode的工厂函数。

var a := Gdvm.DataNodeDict.new(null, TYPE_INT, func():
  return Gdvm.DataNodeInt.new(0)
)

这里的键类型可以是 null ,代表不限定键的类型,即键是一个Variant,值也可以这么设置。

结构型(Struct)

DataNodeStruct

结构型是将数据型节点整合成树的关键类型,会将数据组合成结构体。

有别于字典型,字典型可以随意增删成员,且类型固定。 而结构型增删成员会更麻烦些,且结构型的“键”(属性)只能是String或StringName类型的 (是StringName,String会隐式转换成StringName)。

var a := Gdvm.DataNodeStruct.new()
a.add_property("name", Gdvm.DataNodeString.new("hello"))
a.add_property("age", Gdvm.DataNodeInt.new(18))

var b := Gdvm.DataNodeStruct.new()
b.add_property("info", a)
b.add_property("score", Gdvm.DataNodeFloat.new(99.5))

节点型(Node)

DataNodeNode

节点型是专门用于绑定节点的,因为节点既有属性也有子节点,所以需要同时具有结构型和列表型的特性。

DataNodeNode 继承自 DataNodeStruct,可以使用 DataNodeStruct 的所有方法。

如果要获取子节点的数据结构,可以调用 children() 获取。 得到的是一个 DataNodeList

DataNodeNode 的构造函数需要指定子节点的数据类型和一个工厂函数,用于子节点的生成。

var a := Gdvm.DataNodeNode.new(TYPE_INT, func():
  return Gdvm.DataNodeInt.new(0)
)

a.add_property("name", Gdvm.DataNodeString.new("hello"))
a.add_property("age", Gdvm.DataNodeInt.new(18))

# 获取子节点
var children := b.children()

读与写

写入数据节点的方法是 render(),读取数据节点的方法是 value()

写入时需要自行确定数据类型是否匹配。

var a := Gdvm.DataNodeInt.new(100)
a.render(200)  # 写入数据
var b := a.value()  # 读取数据
prints(b)  # 输出:200

# a.render("hello")  # 错误:类型不匹配

可将一整套组织好的数据,以字典的形式写入一个DataNodeStruct。

var a := Gdvm.DataNodeStruct.new()
a.add_property("name", Gdvm.DataNodeString.new("hello"))
a.add_property("age", Gdvm.DataNodeInt.new(18))
a.render({
  "name": "Zhang San",
  "age": 30,
})

var b := a.value()  # 读取数据
prints(b)  # 输出:{"name": "Zhang San", "age": 30}