今天一同事问我这个问题:S/4HANA Fiori应用里的列表,一旦Scroll到底部就会自动向后台发起新的请求把更多的数据读取到前台显示。算法
以Product Master这个应用为例,我点击搜索以后,结果区域显示当前系统一共有140个product,可是只有前25个返回并显示在浏览器里。浏览器
这个分页效果是UI5 OData的参数实现的:$skip=0&top=25。缓存
而总数140,是经过参数$inlinecount实现,其原理和ABAP Open SQL的SELECT COUNT(*)相似。框架
从Chrome开发者工具能观察到头25个product的payload:工具
当将列表滚动至底部时,第二批共25个product从后台读取出来,显示在前台:ui
这个http请求的参数:$skip=25&top=25,用于读取从第25个到第50个product。this
从调用栈能清楚发现是scroll这个事件触发的第二批product的读取动做。编码
而后再去GrowingEnablement.requestNewPage这一个调用栈,发现一个属性_iLimit维护了一个开始索引,每次scroll到底部的事件触发以后,该属性值都会被GrowingThreshold累加。 由于API this._oControl.getGrowingThreshold每次返回的是一个常量25, 所以_iLimit的值每次scroll到底部以后看起来是这样的:25,50,75,100 ... 这些值会被用来做为HTTP请求参数$skip的值传到后台:spa
我同事的问题:growingThreshold在文件sap.m.ListBase.js里被硬编码成20, 可是运行时在何处被改写成了25?debug
要回答这个问题,须要了解一些UI5 Smart Template的知识,由于例子里这个Product Master的Fiori应用,也是基于Smart Template开发的。能够参考个人博客My understanding about how object page in Smart Template is rendered 来了解其工做原理。
当Product Master这个应用的UI Component被加载并立刻开始渲染时,须要先加载Smart Template的库文件:
在我博客My understanding about how object page in Smart Template is rendered 提到,ListReport.view.xml这个文件里有若干view fragment的声明,每一个声明指向了一些其余的Smart Template库文件。
这些库文件一览:
在Chrome开发者工具查看从ABAP后台加载的库文件SmartTable.fragment.xml,能发现属性growingThreshold在此处被硬编码成25。
当SmartTable.fragment.xml被加载以后其内容会被解析, growingThreshold值为25,会经过控件的setter API写入到控件属性里。这样接下来在处理列表的scroll事件是,25这个值就会经过控件的getter API返回并累加到_iLimit上。
关于XML view从ABAP后台加载到浏览器后是如何被解析并生成对应的UI5控件,能够参考个人博客Why my formatter does not work? A trouble shooting example to know how it works
也许您按照我上面描述的步骤操做,可是没法触发断点。缘由是由于UI5框架针对基于Smart Template开发的Fiori应用的XML view设计了一套缓存机制。当待渲染的XML view已经在缓存中存在时,不会去ABAP后台加载Smart Template的库文件, 而是直接执行第428行的IF分支。
经过调试咱们能够发现缓存是经过IndexedDB加上LRU(Least recently used)算法实现的。
经过Chrome开发者工具能够观察到待渲染的view已经有记录存储在IndexedDB里了:
若是想观察Smart Template库文件的加载,需点击"Delete database"以手动清除缓存。
缓存清除完毕后,便可观察到指望中的Smart Template库文件加载。
这篇文章介绍了如何经过调试找到同事提出问题的答案。我把它加在了我UI5调试文章分享的合集里:My UI5 debugging tips and experience collection - how to resolve UI5 issues through debugging by yourself