Open Fiori Elements 应用里的 visitor 访问者设计模式

举报
汪子熙 发表于 2023/08/06 09:52:17 2023/08/06
【摘要】 Open Fiori Elements 应用 SmartTable title 控件的 text 属性,在运行时如何生成的?在 TitleRenderer.js 里设置断点:调用 getText 拿到 text property 值:问题是这个 Text 属性是从哪里来的?在 SmartTable.js 内部能够观察到这个 Products 字符串:最终的入口还是 XMLTemplatePr...

Open Fiori Elements 应用 SmartTable title 控件的 text 属性,在运行时如何生成的?

在 TitleRenderer.js 里设置断点:

调用 getText 拿到 text property 值:

问题是这个 Text 属性是从哪里来的?

SmartTable.js 内部能够观察到这个 Products 字符串:

最终的入口还是 XMLTemplateProcessor.js:

应该是这些 XML fragment 加载触发的:

把 smarttable.fragment.xml 下载到本地打开,观察其 header 绑定信息:

{= !${parameter>/settings/quickVariantSelection/showCounts} ? ${path: 'header>TypeNamePlural', formatter: 'Open.ui.model.odata.AnnotationHelper.format'} : '' }

根据关键字 TypeNamePlural 进行搜索:

设置了断点,一个也没有触发。
PropertyBinding:

一个 visitor 模式:

源代码:

/**
			 * Visits the given attribute of the given element. If the attribute value represents a
			 * binding expression that can be resolved, it is replaced with the resulting value.
			 *
			 * @param {Element} oElement the XML DOM element
			 * @param {Attr} oAttribute one of the element's attribute nodes
			 * @param {Open.ui.core.template._with} oWithControl the "with" control
			 * @returns {Open.ui.base.SyncPromise}
			 *   A sync promise which resolves with <code>undefined</code> as soon as the
			 *   attribute's value has been replaced, or is rejected with a corresponding error if
			 *   getting the binding's value fails.
			 */
			function visitAttribute(oElement, oAttribute, oWithControl) {
				if (fnSupportInfo) {
					fnSupportInfo({context:undefined /*context from node clone*/, env:{caller:"visitAttribute", before: {name: oAttribute.name, value: oAttribute.value}}});
				}
				return resolveAttributeBinding(oElement, oAttribute, oWithControl)
					.then(function () {
						if (fnSupportInfo) {
							fnSupportInfo({context:undefined /*context from node clone*/, env:{caller:"visitAttribute", after: {name: oAttribute.name, value: oAttribute.value}}});
						}
					});
			}

			/**
			 * Visits all attributes of the given element. If an attribute value represents a
			 * binding expression that can be resolved, it is replaced with the resulting value.
			 *
			 * @param {Element} oElement the XML DOM element
			 * @param {Open.ui.core.template._with} oWithControl the "with" control
			 * @returns {Open.ui.base.SyncPromise}
			 *   A sync promise which resolves with <code>undefined</code> as soon as all
			 *   attributes' values have been replaced, or is rejected with a corresponding error if
			 *   getting some binding's value fails.
			 */
			function visitAttributes(oElement, oWithControl) {
				/*
				 * Comparator for DOM attributes by name.
				 *
				 * @param {Attr} oAttributeA
				 * @param {Attr} oAttributeB
				 * @returns {number} <0, 0, >0
				 */
				function comparator(oAttributeA, oAttributeB) {
					return oAttributeA.name.localeCompare(oAttributeB.name);
				}

				return stopAndGo(
					// Note: iterate over a shallow copy to account for removal of attributes!
					// Note: sort attributes by name to achieve a stable log order across browsers
					Array.prototype.slice.apply(oElement.attributes).sort(comparator),
					function (oAttribute) {
						return visitAttribute(oElement, oAttribute, oWithControl);
					});
			}

这段代码中所使用的设计模式为访问者模式(Visitor pattern)。

访问者模式是一种将算法与对象结构分离的设计模式。这种模式在对象结构中的元素上定义一个访问操作,该操作以一个访问者作为参数,访问者在该操作中实现了一个针对该元素的操作。

在这段代码中,visitAttributevisitAttributes 函数就充当了访问者的角色。它们对 XML DOM 元素及其属性进行访问,解析属性中可能存在的绑定表达式,并将解析后的结果替换原始属性值。

例如,visitAttribute 函数访问单个属性,通过 resolveAttributeBinding 解析可能的绑定表达式,并通过 Promise 结构异步替换属性值。而 visitAttributes 函数则访问元素的所有属性,通过调用 visitAttribute 对每个属性进行处理。

这种通过访问者访问和处理元素的方式,将元素与处理逻辑分离,增加了代码的可扩展性和复用性。当需要对元素进行新的操作时,只需要定义新的访问者,而无需修改元素类。同时,访问者模式也使得添加新的操作变得更简单,只需添加一个新的访问者即可。

这段代码还体现了访问者模式的另一特性,即访问者可以累积状态。在这段代码中,访问者通过 Promise 结构返回处理结果,这可以看作是访问者在访问过程中累积的状态。通过 Promise 结构,可以方便地处理异步操作和错误,这也是访问者模式的一种常见应用。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。