在我的UI5应用程序中,我有一个表(sap.m.Table
)的视图,填充来自后端onInit
钩子的数据。问题是每个视图实例只执行一次onInit
:
每个View实例只调用一次,与
onBeforeRendering
和onAfterRendering
钩子不同。
并且如果用户决定离开该视图(例如,返回导航)并稍后重新打开它,则不会调用onInit
,因此将不再检索数据,并且表内容将不反映可能的变化。
为了确保每次打开视图时都检索数据,我试图在onBeforeRendering
上获取数据,但是这个钩子也只调用一次。我发现,每次打开视图时强制调用onBeforeRendering
的唯一方法是将以下代码添加到onInit
方法中:
onInit: function () {
this.getView().addEventDelegate({
onBeforeShow: this.onBeforeShow,
}, this);
}
我的问题:
onInit
上面的代码片段,为什么每次显示视图时都不会触发onBeforeRendering
?patternMatched
和routeMatched
。但这三种方法中哪一种更为常见?
- 为什么(...)是每次显示视图时都没有触发
onBeforeRendering
?
我认为对“渲染”的含义存在误解。在UI5中,当某些东西“渲染”时,RenderManager
正在编写一个完整的新DOM元素;即onBeforeRendering
在控制的render
函数(在我们的例子中,视图)之前调用.src
这并不意味着在浏览器将元素绘制到屏幕之前调用它(为此,现代浏览器提供本机API,例如Intersection Observer)。
回到这个问题; on*Rendering
未被触发的原因是因为之前已经呈现过控件。当用户通过navTo
导航然后再返回时,可以看到这一点。相应的视图元素已经在DOM中,因此不需要再次调用render
,这意味着没有触发on*Rendering
。
- 代码片段到底做了什么?
onInit: function () { this.getView().addEventDelegate({ onBeforeShow: this.onBeforeShow, }, this); }
addEventDelegate
为控件(而不是控件)触发的事件添加了一个监听器。
例如:view contains events像afterInit
,beforeExit
,......
由于addEventDelegate({onAfterInit})
被此控件(视图)触发,因此执行afterInit
将无法正常工作。
做addEventDelegate({onmouseover})
工作,因为它在这个控件上被解雇了。
这同样适用于onBeforeShow
。该视图不包含任何事件,如beforeShow
,afterShow
等。这些是由NavContainer
在视图上触发的(例如<App>
对其孩子,视图)。有关这些事件的文档可在以下位置找到:
另见类似问题Why does onBeforeFirstShow work?
- 替代技术:使用
patternMatched
(...)。但这三种方法中哪一种更为常见?
通过“三种方法”,我认为你的意思是:
on*Rendering
(第一种方法),on*Show
(第二种方法),patternMatched
(第3种方法)。答案是,一如既往,这取决于你想要实现的目标。但通常,我们:
NavContainerChild
),请使用第二种方法(sap.ui5/routing
事件)。onAfterShow
的第二种方法。见How to Set Initial Focus in a View?NavContainerChild
)时执行某些操作,例如,在导航到详细信息页面后执行Context Binding。这个怎么运作:
调用router.navTo()
时,将创建下一个相应的视图和控制器。
在新创建的控制器的onInit
中,您指定了patternMatched
handler。
在导航时,URL哈希值将更改。路由器(在HashChanger
内部)注意到URL更改,导致路由触发patternMatched
,通过该路由器将调用您的处理程序。onBeforeRendering
和onAfterRendering
中做任何事情,因为从应用程序的角度来看,调用render
函数的频率是不可预测的。对于控件开发人员来说,这些钩子是绝对必要的。但对于应用程序开发人员来说,通常有更好的选择问题#3:
当你的路由器在URL或patternMatched
方法上匹配时,router.navTo
会受到攻击。
routeMatched
将在与patternMatched
相同的场合受到打击,当它的儿童路线被导航到时。
想象一下,你有一条关于路线A的主视图和它在路线B上的细节。如果用户直接导航到路线B,那么渲染与路线B相关联的目标以及与路线A相关联的目标是有意义的。
总结:
patternMatched
:直接路线匹配routeMatched
:
此路由器中的路由模式。
其子路线的模式。
其嵌套路线的模式。发生这种情况时,使用嵌套路由的实例设置nestedRoute
参数。你应该用
onInit: function() {
let route = this.getOwnerComponent().getRouter().getRoute("yourroutename");
route.attachPatternMatched(this.onRoutePatternMatched, this);
// ...
},
每次在路由配置中匹配路由模式时,都会触发此路由事件。在上面的示例中,每次通过导航加载路径时都会调用函数onRoutePatternMatched
。
onRoutePatternMatched: function(event) {
// this logic will repeat itself every time the route pattern is matched
},