SAP UI5 和 CRM WebUI 的 View 和 Controller 是如何绑定的

UI5
例如我在 UI5 的界面上画一个按钮,点击之后弹出一个 Alert dialog。

在 XML view 里只定义了 controller 的名称和事件处理函数的名称。那么按钮被点击之后,controller 的 onShowHello 被触发。但是,这个 controller 的实例是什么时候被创建, 并且关联到这个申明它的 XML view 里呢?

在 XMLView.js 里,我定义的 XML view 的源代码被加载之后,XMLView 会调用 XMLTemplateProcessor, 解析 XML view 的内容,根据里面的 control 申明创建对应的 UI5 控件实例。下图的变量_xContent.innerHTML 即为上图 XML view 的源代码。

XMLView 的实例通过工厂模式创建之后,XMLView 源代码里定义的 controller 名称 sap.ui.demo.walkthrough.controller.App,会赋到 oView 实例的字段_controllerName 上。

View 和 Controller 的绑定是通过这个方法 createAndConnectController 完成:
connect controller to view after controller and control tree are fully initialized

Controller 的实例也通过工厂模式创建:

一旦 connectToView 执行之后,

oView 和 oController 的关联关系就建立起来了。

CRM WebClient UI
每个 UI component view 里有一个 built-in 的属性 controller, 指向这个 view 对应的 controller 实例。

在 BSP 的编程环境里,开发人员根本无需操心这个 controller 实例的初始化,直接用就行。
那么 View 的 controller 实例究竟在什么时候被框架初始化的?
要自己搞清楚这个问题,可以随便找个 BSP UI component 做个实验。我找的是 PRDHS。在其 View 的 controller CL_PRDHS_HEADER_IMPL 的构造函数里设置断点:

打开该 view,从调用栈上下文即可得知 BSP 框架在什么地方初始化 controller 实例的。记下这个实例在 ABAP runtime 的地址编号 4633:

同 UI5 逻辑类似,在 CL_BSP_PAGE_BASE~CREATE_PAGE 内部,第 190 行创建 controller 的实例并将其同 View 实例建立关联关系。

最后运行时 View 的 controller 实例 4633 和之前我们在 PRDHS/Header 的 controller CL_PRDHS_HEADER_IMPL 的构造函数中的 me 指针 4633 一样,证明两个变量指向的是同一个实例。

要获取更多 Jerry 的原创技术文章,请关注公众号"汪子熙":

版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/dea1e4bd801a0c14d5057d0e0】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论