SAPUI5 1.38.55自定义MessagePopoverItem模板显示subtitle问题咨询
- 原有自定义SAPUI5应用最初使用1.40.11版本,因该版本从CDN下架,切换到长期维护的兼容版本1.38.55
- 版本切换后发现1.38.55版本的
sap/m/MessagePopoverItem控件未提供subtitle属性,因此尝试通过自定义控件重写MessagePopoverItem模板,实现副标题展示 - 自定义控件实现过程中出现资源加载报错:框架未从本地路径加载自定义渲染器,反而尝试从CDN拉取不存在的
sap/m/MessagePopoverItemRenderer.js资源,返回404错误 - 参考同类渲染器404问题的方案编写了自定义控件与对应渲染器代码后,仍未解决问题,核心疑问为:
- 是否可以通过自定义控件的方式修改MessagePopover的条目模板?
- 渲染器跨路径加载报错如何修复?
自定义控件代码
sap.ui.define([ "sap/m/MessagePopoverItem", "./CustomMessagePopupItemRender", ], function (MessagePopoverItem,CustomMessagePopupItemRender) { "use strict"; return MessagePopoverItem.extend("demoapp.customControls.CustomMessagePopoverItem", { renderer:CustomMessagePopupItemRender, metadata : { properties: { subtitle: { type: "string", defaultValue: "" } } }, onAfterRendering: function() { if(MessagePopoverItem.prototype.onAfterRendering) { MessagePopoverItem.prototype.onAfterRendering.apply(this, arguments); } if(this.getTitle() !== "") { var oHl = this.$().find(".sapMLIBContent"); var ss = oHl; } } }); });
自定义渲染器代码
sap.ui.define([ "sap/ui/core/Renderer", ], function(Renderer) { "use strict"; return Renderer.extend("demoapp.customControls.CustomMessagePopupItemRender", { apiVersion: 2, render: function(renderManager, control) { // 1.88版本前存在render函数重复调用问题 const child = control.getAggregation("content"); if (child && child.isA("sap.ui.core.Control")) { renderManager.openStart("div", control) .accessibilityState(control, { role: "tooltip" }) .style("max-width", "95vw") .style("width", control.getWidth()) .openEnd() .renderControl(child) .close("div"); } else { renderManager.openStart("span", control) .accessibilityState(control, { role: "tooltip" }) .style("max-width", "90vw") .style("width", control.getWidth()) .style("padding", "0.5rem") .class("sapThemeBaseBG-asBackgroundColor") .openEnd() .text(control.getText()) .close("span"); } }, }); });
自定义扩展MessagePopoverItem实现自定义条目模板、增加subtitle属性的方案完全可行,渲染器404问题和渲染异常由几个明确的版本兼容问题和写法错误导致,按以下规则修复即可。
修复404加载报错
1.38是早期长期维护版本,该版本中sap/m/MessagePopoverItem的渲染器是直接内联在控件源码中的,没有单独发布独立的MessagePopoverItemRenderer.js资源。原有写法把渲染器拆成独立模块导入,框架在解析子类继承关系时,没有正确识别到子类自带的渲染器配置,就会按默认资源加载规则去CDN的sap/m路径下查找父类的独立渲染器文件,自然返回404。
修复方式:不要单独拆独立的renderer文件做导入,直接把自定义渲染器内联写在自定义控件的模块文件中,控件定义时直接挂载渲染器对象,从根源上避免框架触发父类渲染器的查找逻辑。修复渲染器API兼容问题
原有渲染器中添加的apiVersion: 2配置是UI5 1.70之后版本才支持的新渲染API,1.38版本完全不识别该配置,会直接导致渲染逻辑执行失败。
修复方式:删除apiVersion: 2配置,全部使用1.38版本兼容的传统RenderManager API编写渲染逻辑。修正渲染逻辑匹配问题
原有代码套用的是Tooltip控件的渲染逻辑,而MessagePopoverItem是继承自ListItemBase的列表项控件,结构、交互、样式都和Tooltip完全无关,直接套用会导致条目渲染完全错乱。
修复方式:自定义渲染器不需要从零编写整个条目的渲染逻辑,直接调用父类MessagePopoverItem自带的渲染方法完成原有结构渲染,再在对应位置追加subtitle节点的渲染代码即可,既减少代码量,也能完全兼容原有控件的样式、交互逻辑。
修复后可运行参考代码
不需要单独创建外部Renderer文件,直接在自定义控件模块中内联渲染器即可:
sap.ui.define([ "sap/m/MessagePopoverItem", "sap/m/MessagePopoverItemRenderer" ], function (MessagePopoverItem, MessagePopoverItemRenderer) { "use strict"; // 内联自定义渲染器 var CustomPopoverItemRenderer = sap.ui.core.Renderer.extend(MessagePopoverItemRenderer); CustomPopoverItemRenderer.render = function(oRm, oControl) { // 先调用父类渲染逻辑,完成原生条目结构渲染 MessagePopoverItemRenderer.render(oRm, oControl); // 在原有结构后追加subtitle节点 if (oControl.getSubtitle()) { oRm.write('<div class="customMPopoverSubtitle" style="font-size: .875rem; color: #6a6d70; margin-top: .25rem;">'); oRm.writeEscaped(oControl.getSubtitle()); oRm.write('</div>'); } }; return MessagePopoverItem.extend("demoapp.customControls.CustomMessagePopoverItem", { renderer: CustomPopoverItemRenderer, metadata : { properties: { subtitle: { type: "string", defaultValue: "" } } } }); });
使用注意事项
- 自定义控件开发完成后,在MessagePopover配置items聚合的绑定模板时,必须使用自定义的
demoapp.customControls.CustomMessagePopoverItem作为模板,不能再使用原生的MessagePopoverItem,否则subtitle属性不会生效。 - 如果需要调整subtitle的样式,建议给追加的subtitle节点加自定义class,在应用的CSS文件中编写对应样式,不要硬编码内联样式,方便后续主题适配。
内容的提问来源于stack exchange,提问作者tarzanbappa

