ServiceNow Angular.js门户组件模板修改后缓存异常问题排查
问题分析:ServiceNow Angular门户组件模板修改后的缓存异常
在ServiceNow Angular.js门户中,为避免克隆组件,自行创建组件嵌入目标组件relevant_for_you,并在客户端脚本中修改其HTML模板。但出现异常:导航到其他使用该嵌入组件的页面时,页面会渲染修改后的模板,刷新后才恢复正常。控制台输出另一页面的模板内容时并无新增的arrow-container元素,但页面显示已修改,疑似缓存导致。
服务器脚本
data.widget = $sp.getWidget('relevant_for_you', options);
客户端脚本
let widgetsData = c.data.widget.data.widgetsData; widgetsData.forEach(item => { // 克隆并修改模板 let thisWidgetTemplate = item.data.widgetData.template.slice(0); // 从HTML字符串创建临时jQuery对象 let $tempDiv = $('<div>').html(thisWidgetTemplate); // 查找目标容器 let $contentContainer = $tempDiv.find('.content-card-container'); if ($contentContainer.length > 0) { // 创建新元素 let $newElement = $('<div>', { class: 'arrow-container', text: item.data.widgetData.orderMessage }); // 追加到容器 $contentContainer.append($newElement); // 更新模板 thisWidgetTemplate = $tempDiv.html(); // 赋值回原对象 item.data.widgetData.template = thisWidgetTemplate; } });
组件HTML模板
<div class="{{c.options.sp_column}}"> <div ng-class="{'negative-margin': options.negative_top_margin === 'true' && c.location.indexOf('$spd.do') === -1}"> <sp-widget widget="data.widget"></sp-widget> </div> </div>
问题根源
- ServiceNow Widget实例缓存:
$sp.getWidget()返回的widget实例会被门户框架在SPA导航场景下缓存。客户端修改item.data.widgetData.template后,修改会作用在缓存的实例上,后续页面复用该实例时就会渲染已修改的模板。 - AngularJS引用传递特性:客户端直接修改了
c.data.widget.data.widgetsData中的对象属性,而c.data.widget是服务器返回的引用。SPA导航时门户不会重新初始化所有组件,复用的引用会把修改带至其他页面。 - 数据与渲染不一致:控制台输出的是新页面从服务器获取的原始模板数据,但页面渲染用的是缓存实例里的已修改模板,所以出现数据和显示不符的情况。
解决建议
- 避免直接修改缓存实例数据:不在客户端直接修改
c.data.widget下的模板,改用服务器脚本传递修改后的模板,或创建独立widget实例而非复用缓存。 - 替换为
$sp.getWidgetInstance():若ServiceNow版本支持,用$sp.getWidgetInstance()替代$sp.getWidget(),确保每次导航获取全新实例。 - 组件销毁时清理修改:利用AngularJS的
$on('$destroy')事件,在组件销毁时将模板恢复为原始状态,避免影响后续页面。
内容的提问来源于stack exchange,提问作者Kenny Bones
相关产品推荐
相关产品推荐

