写点什么

深入学习 SAP UI5 框架代码系列之七:控件数据绑定的三种模式 - One Way, Two Way 和 OneTime 实现原理比较

作者:Jerry Wang
  • 2021 年 11 月 28 日
  • 本文字数:2135 字

    阅读完需:约 7 分钟

深入学习 SAP UI5 框架代码系列之七:控件数据绑定的三种模式 - One Way, Two Way 和 OneTime 实现原理比较

如果是从 Angular 前端开发转过来的 SAP UI5 应用开发人员,想必对 Angular 的 Property binding,Event binding 和 Two-way binding 的实现原理和区别已经有所了解了。



Angular 这三种绑定方式的使用语法如下图所示:



但咱们本文不会阐述 Angular 的数据绑定细节,而是继续聚焦在 SAP UI5 的数据绑定三种模式的探讨上。


Jerry 前一篇文章 深入学习SAP UI5框架代码系列之六:SAP UI5控件数据绑定的实现原理,曾经展示过这张源代码截图,第 83 行包含了 SAP UI5 支持的三种数据绑定模式:


(1) OneWay:单向绑定(2) TwoWay:双向绑定(3) OneTime:单次绑定



从第 69 行代码得知,SAP UI5 模型的默认绑定方式为双向绑定 TwoWay.


当我第一次了解了 SAP UI5 三种不同的数据绑定模式时,脑子里马上浮现出一个问题:


在我们的脚手架应用里,将 button 控件的 text 属性,通过 bindProperty 函数,绑定到 JSONModel 实例的 field_for_text 字段上时,使用的是哪一种绑定模式?


oButton1.bindProperty("text", "/field_for_text");
复制代码


答案是 TwoWay,双向绑定。在调试器里,通过下图路径即可查看:


oButton1.mBindingInfos.text.binding.sMode.
复制代码



方法 bindProperty 里创建 oBinding 对象时,把 JSONModel 的默认 binding 方式(sDefaultBindingMode), TwoWay, 赋给 oBinding 对象。


SAP UI5 双向绑定的实现原理 - 数据从控件流向模型

我们调用控件的 setText 方法,修改控件 text 属性。根据 SAP UI5 数据双向绑定特性,控件 text 属性绑定到的模型字段 field_for_text 的值,也会自动被修改:


oButton1.setText("用js修改控件值");
复制代码



从上图我们能确认,JSONModel 模型实例的 field_for_text 也跟着被修改了。这一切是怎么发生的?


答案在 Jerry 之前的文章 深入学习SAP UI5框架代码系列之五:SAP UI5控件的实例数据修改和读取逻辑 介绍的 button 控件的 setText 方法里,其实已经提到过。


下图第 1320 行的代码,执行的逻辑正是在控件属性通过 setProperty 被更新的场景下,将最新值同步到对应的模型字段中去。



在 updateModelProperty 函数内部,有一个 IF 条件判断:只有当前 oBinding 对象实例的绑定模式为 TwoWay 时,才调用其 setExternalValue 方法,将模型字段的对应值,修改成来自控件属性通过 setText 更改的最新值。


这就是控件 text 属性的变化,能传递到对应模型字段的原理。


SAP UI5 单向绑定的工作原理

通过之前的介绍我们得知,SAP UI5 控件绑定的默认模式为 TwoWay. 因此,我们如果要测试单向绑定,需要对已有的代码进行修改,将绑定模式显式修改成 OneWay:


oButton1.bindProperty("text", "/field_for_text", undefined, "OneWay");
复制代码


此时,控件 text 属性通过 setText 的修改,不会再触发 JSONModel 模型字段的变化,因为下图 3620 行 IF 语句的条件不再成立。这就是 SAP UI5 单向数据绑定的原理:数据仅仅会在模型字段到控件属性这个方向上单向流动。JSONModel 字段值发生变化后,控件对应属性会自动更新。反之,控件属性通过 API 被修改时,不会引起 JSONModel 字段值的更新。


SAP UI5 单次绑定的工作原理

SAP UI5 官方网站上对单次绑定(OneTime)的说明:value is only read from the model once.


怎么理解这句话呢?



通过一个实际的例子来理解双向绑定和单次绑定的区别。


在双向绑定的测试代码里,添加如下两行代码:


myData["field_for_text"] = "Tom";oModel.checkUpdate();
复制代码



模型字段 field_for_text 的初始值,在第 28 行赋值为 Jerry, 然后在第 34 行设置为 Tom. 调用模型的 checkUpdate 方法后,控件的标签也自动刷新为 Tom.


JSONModel 的 checkUpdate 方法,会使用_fireChange,以事件通知的方式,将最新的 Tom 值广播出去。



that.updateProperty 最后会调用 SAP UI5 控件的 setProperty 方法,把 text 属性的值赋成 Tom.


下图展示的 setProperty 方法,在 Jerry 之前的文章 深入学习SAP UI5框架代码系列之五:SAP UI5控件的实例数据修改和读取逻辑 里有详细介绍。



现在开始测试单次绑定,将 32 行 bindProperty 函数调用里的绑定模式改成 OneTime:



测试发现,在单次绑定模式下,SAP UI5 控件属性和模型字段的自动同步已经中断了——button 控件的 text 属性,保存的是调用 bindProperty 方法那一刻,JSONModel 的 field_for_text 值 Jerry,而不是数据绑定之后,修改成的最新值 Tom.


这个行为正是 SAP UI5 单次绑定的正确表现。



那么为什么在单次绑定模式下,纵然我们调用了模型的 checkUpdate 方法,仍然无法将模型字段的最新值,通过 change 事件通知机制告诉给控件的监听函数呢?


答案就是,在 SAP UI5 控件指定了单次绑定的模式后,它"过河拆桥",马上就把响应模型 change 事件的监听函数拆除了(detach,取消注册之意)。



奥妙就在下图 3379 行代码的 IF 分支里:在 SAP UI5 控件调用 bindProperty 方法把控件属性绑定到模型字段时,如果当前绑定模式为 OneTime,则取消控件针对模型 change 事件的监听函数注册。


如此一来,不论接下来模型字段的值如何变化,该变化的值通过 change 事件进行广播,但 UI5 控件再也不会收到该事件了,因而控件属性也不会再刷新。



Jerry 在 SAP UI5 / Angular 的实际开发生涯中,一旦遇到数据绑定出问题,总能迅速找到如何排错的突破口,靠的就是对这些前端框架的数据绑定细节的熟悉。


希望本文能帮助大家对 SAP UI5 官方网站上解释数据绑定三种方式的说明文字,有更深入的理解,感谢阅读。



本系列下一篇文章,我们会介绍 SAP UI5 控件 ID 的生成逻辑,敬请期待。

发布于: 2 小时前阅读数: 10
用户头像

Jerry Wang

关注

个人微信公众号:汪子熙 2017.12.03 加入

SAP成都研究院开发专家,SAP社区导师,SAP中国技术大使。

评论

发布
暂无评论
深入学习 SAP UI5 框架代码系列之七:控件数据绑定的三种模式 - One Way, Two Way 和 OneTime 实现原理比较