# 利用bi.loader快速封装分页加载更多列表 长列表,从后端分页加载,搜索也由后端处理. 非常常见的需求 用过ButtonGroup的都知道格式化好items,然后直接populate就行了. Loader也类似,只是他还具有itemsCreator的能力 [bi.loader](https://code.fineres.com/projects/VISUAL/repos/fineui/browse/src/base/combination/loader.js) ```javascript class MyList extends BI.Widget { hasNext = false; render() { return { type: "bi.loader", itemsCreator: (op, callback) => { const times = op.times; // times标记分页码 setTimeout(() => { callback(this.formatItems(/* some datas */)); }); }, hasNext: () => this.hasNext }; } formatItems(items) { // 一般格式化节点常用的状态 let keyword; let selected; let disabled; return items.map(item => { return { ...item, keyword, selected, disabled, }; }); } } ``` 常见操作手法 ### bi.loader依旧支持items属性,如果非空,会直接渲染出来作为第一页 ### bi.loader可以直接调用空的populate方法,其会自动触发itemsCreator请求数据 利用这种机制可以将数据请求集中化. 无需在筛选条件变化之后,手动去请求来数据,然后再populate到Loader里面 ```javascript class MyList extends BI.Widget { watch = { "keyword | filter | perPage": () => { this.loader.populate(); } }; render() { return { type: "bi.loader", ref: ref => this.loader = ref, itemsCreator: (op, callback) => { const times = op.times; // times标记分页码 requestItems(op.times, callback(/* some datas */)); }, }; } requestItems(page, cb) { // 一般常用的请求条件 let keyword; let filter; let perPage; fetchData({ page, keyword, filter, perPage, }).then(cb); } } ``` ### hasNext的处理怎么才能更优雅 查阅内部源码,hasNext可以利用count props,也可以由外部回调 这样就有两种操作姿势 1. 在itemsCreator回调的时候修改props`this.loader.attr("count",res.allCount)` 2. 在itemsCreator回调的时候保存状态,hasNext回调给loader `hasNext:() => this.hasNext` 孰优孰劣见仁见智,但有没有更符合开发直觉的方式呢? 例如 `callback({items,hasNext,count})`, coming soon