每次打开视图时都不会调用onBeforeRendering

问题描述 投票:3回答:3

在我的UI5应用程序中,我有一个表(sap.m.Table)的视图,填充来自后端onInit钩子的数据。问题是每个视图实例只执行一次onInit

每个View实例只调用一次,与onBeforeRenderingonAfterRendering钩子不同。

并且如果用户决定离开该视图(例如,返回导航)并稍后重新打开它,则不会调用onInit,因此将不再检索数据,并且表内容将不反映可能的变化。

为了确保每次打开视图时都检索数据,我试图在onBeforeRendering上获取数据,但是这个钩子也只调用一次。我发现,每次打开视图时强制调用onBeforeRendering的唯一方法是将以下代码添加到onInit方法中:

onInit: function () {
  this.getView().addEventDelegate({
    onBeforeShow: this.onBeforeShow,
  }, this);
}

我的问题:

  1. 如果没有onInit上面的代码片段,为什么每次显示视图时都不会触发onBeforeRendering
  2. 上面的代码片段到底有什么作用?
  3. 替代技术:使用patternMatchedrouteMatched。但这三种方法中哪一种更为常见?
sapui5
3个回答
4
投票
  1. 为什么(...)是每次显示视图时都没有触发onBeforeRendering

我认为对“渲染”的含义存在误解。在UI5中,当某些东西“渲染”时,RenderManager正在编写一个完整的新DOM元素;即onBeforeRendering在控制的render函数(在我们的例子中,视图)之前调用.src

这并不意味着在浏览器将元素绘制到屏幕之前调用它(为此,现代浏览器提供本机API,例如Intersection Observer)。

回到这个问题; on*Rendering未被触发的原因是因为之前已经呈现过控件。当用户通过navTo导航然后再返回时,可以看到这一点。相应的视图元素已经在DOM中,因此不需要再次调用render,这意味着没有触发on*Rendering


  1. 代码片段到底做了什么? onInit: function () { this.getView().addEventDelegate({ onBeforeShow: this.onBeforeShow, }, this); }

addEventDelegate为控件(而不是控件)触发的事件添加了一个监听器。

例如:view contains eventsafterInitbeforeExit,...... 由于addEventDelegate({onAfterInit})被此控件(视图)触发,因此执行afterInit将无法正常工作。 做addEventDelegate({onmouseover})工作,因为它在这个控件上被解雇了。

这同样适用于onBeforeShow。该视图不包含任何事件,如beforeShowafterShow等。这些是由NavContainer在视图上触发的(例如<App>对其孩子,视图)。有关这些事件的文档可在以下位置找到:

另见类似问题Why does onBeforeFirstShow work?


  1. 替代技术:使用patternMatched(...)。但这三种方法中哪一种更为常见?

通过“三种方法”,我认为你的意思是:

  • on*Rendering(第一种方法),
  • on*Show(第二种方法),
  • 以及上面提到的路线事件,如patternMatched(第3种方法)。

答案是,一如既往,这取决于你想要实现的目标。但通常,我们:

  • 如果应用程序没有路由概念(manifest.json中没有NavContainerChild),请使用第二种方法(sap.ui5/routing事件)。
  • 如果要在显示视图后设置初始焦点,请使用onAfterShow的第二种方法。见How to Set Initial Focus in a View?
  • 使用第3种方法获得有关匹配的路由模式的通知。这种方法通常用于每次显示视图(NavContainerChild)时执行某些操作,例如,在导航到详细信息页面后执行Context Binding。这个怎么运作: 调用router.navTo()时,将创建下一个相应的视图和控制器。 在新创建的控制器的onInit中,您指定了patternMatched handler。 在导航时,URL哈希值将更改。路由器(在HashChanger内部)注意到URL更改,导致路由触发patternMatched,通过该路由器将调用您的处理程序。
  • ⚠️个人意见:避免作为应用程序开发人员的第一种方法。避免在onBeforeRenderingonAfterRendering中做任何事情,因为从应用程序的角度来看,调用render函数的频率是不可预测的。对于控件开发人员来说,这些钩子是绝对必要的。但对于应用程序开发人员来说,通常有更好的选择

2
投票

问题#3:

当你的路由器在URL或patternMatched方法上匹配时,router.navTo会受到攻击。

routeMatched将在与patternMatched相同的场合受到打击,当它的儿童路线被导航到时。

想象一下,你有一条关于路线A的主视图和它在路线B上的细节。如果用户直接导航到路线B,那么渲染与路线B相关联的目标以及与路线A相关联的目标是有意义的。

总结:

  • patternMatched:直接路线匹配
  • routeMatched: 此路由器中的路由模式。 其子路线的模式。 其嵌套路线的模式。发生这种情况时,使用嵌套路由的实例设置nestedRoute参数。

2
投票

你应该用

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
},
© www.soinside.com 2019 - 2024. All rights reserved.