DynamicDSL将遵循以下的交互展示逻辑: 描述文件(XML,Widget) --->(绑定数据)--->渲染模板--->渲染--->事件驱动--->数据改变 这样循环下来的,最终我们看到的就是App上的界面与交互效果了。
这看上去和RN,flutter有点像,只是我们这个是特定场景的使用。
实现了AST节点,已经有了动态计算数据的能力,接下来我们将实现动态XML模板的绑定,为渲染前生成布局描述模板。
<View>
<View text="年龄: {{ 33.22 * 2}}" color="{{ item[age] >= 20 ? '#FFFFFF' : '#DDDDDD' }}" />
class="hljs-name"View>
这个模板比较简单,它有一个根节点,根节点有一个子节点包含两个属性,我们用"{{ }}"来描述需要计算的表达式,如果没有两个大括号则认为是原始字符串。
「这里我们规定,布局模板必须在一个根节点下面!」
XML原始节点展示如下:
text节点可以直接计算出结果, color节点通过获取环境变量中名称为item的数据,再进一步获取其中名称为age的数据与20进行比较,再得到具体的值。
R"({"item":{"age": 30}})"
动态绑定之后结果如下:
到此,可以认为这个XML是我们基础布局模板,可以拿给Flex引擎计算了。
在组件布局的时候还时常需要对组件节点进行重复或者显示与隐藏等操作,因此: 我们规定
for="{{for xx item xxs}}" 用于实现重复组件
if="{{ expr }}" 用于实现节点是否显示
现在我们将XML的描述修改成下面这样:
<View>
<View text="年龄: {{ 33.22 * 2}}" info="{{ item[name] }} : {{item[age]}}" color="{{ item[age] >= 20 ? '#FFFFFF' : '#DDDDDD' }}" for="{{ for item in items }}"/>
class="hljs-name"View>
XML原始节点展示如下:
首先我们需要遍历节点的属性,查找到节点中for字段的值是否为一个有效的循环表达式,然后对该循环表达式进行计算展开,结果如下:
R"({"item":{"age": 30},"items":[{"name": "小强", "age": 28},{"name": "小明", "age": 23},{"name": "小红", "age": 18}]})"
**「这里需要特别注意的是:For会产生一个新的变量环境,for语句中定义了一个新的变量,当我们在展开时需要将新的变量(item)注入到变量环境中,item将覆盖上一级环境变量中的item的值。
这与栈帧调用时的本地变量覆盖上一级范围中的变量是一样的道理。
」** 展开之后,item是items中的每一个元素而不是根节点上的item了。
此时再对每个节点进行消解运算
注入的环境变量如下:
if语句相对简单一点,它不会产生新的变量,只需要对表达式求值,获取表达式的结果true则保留,false则删除节点不展示。
测试一下,对一个相对复杂的模板进行动态绑定:
<View>
<View text="年龄: {{ 33.22 * 2}}" color="{{ item[age] >= 20 ? '#FFFFFF' : '#DDDDDD' }}" for="{{ for item in items }}">
class="hljs-name"View>
<View>
<View for="{{ for item in items }}">
展示结果如下,「这里需要注意的是当一个父节点在循环的时候,它的子节点也同样会得到for生成的新变量,在展开子节点计算其属性时,也能获取到新的变量从而得到想要的结果。」
到这里,动态绑定就差不多了,接下来就是将绑定后的模板交给Flex引擎,计算而已了。
如果你觉得这个文章对你有用,可以分享给更多的朋友。
谢谢!
全部0条评论
快来发表一下你的评论吧 !