明天讲一个治理后盾罕用的性能,表格性能
需要剖析
首先看看上面的表格页面,有筛选,分页,渲染等性能
依据这些性能咱们能够定义出页面视图须要的数据模型
视图数据模型
首先是分页相干的数据
interface Pagination {
current: number;
total: number;
pageSize: number;
}
- data: 每一行的数据
- params: 申请参数
-
loading: …
export interface TableState<Row = any> { loading: boolean; data: Row[]; params: Record<any, any>; pagination: Pagination & Record<string, any>; [p: string]: any; }
有了这些数据就能够满足一个表格的失常渲染了
视图操作方法
接下来定义一些表格须要的操作方法
loading 管制
这里咱们用两个办法来管制 loading 的切换
showLoading() {if (this._loadingCount === 0) {this.setState((s) => {s.loading = true;}); } this._loadingCount += 1; } hideLoading() { this._loadingCount -= 1; if (this._loadingCount === 0) {this.setState((s) => {s.loading = false;}); } }
fetchData
获取数据的办法,这里咱们定义一个异步函数,申明好接口定义,函数内容间接抛错,须要等具体应用在去实现真正的 fetchData
async fetchData(params: Partial<TableState['params']> & { current: number; pageSize: number; }, ): Promise<{data: any[]; current: number; pageSize: number; total: number; }> {throw Error('请实现 fetchTable'); }
updateData
updateData 办法用来调用 fetchData,更新数据,切换 loading
/** * 发申请,更新数据 * @returns */ updateData() {const params: Record<any, any> = {}; Object.entries(this.state.params || {}).forEach(([k, v]) => {if (v !== undefined) {Object.assign(params, { [k]: v }); } }); this.showLoading(); return this.fetchData({ current: this.state.pagination.current || 1, pageSize: this.state.pagination.pageSize || 10, ...params, }) .then((res) => {this.setState((s) => { s.pagination.current = res.current; s.pagination.pageSize = res.pageSize; s.pagination.total = res.total; s.data = res.data; }); return res; }) .finally(() => {this.hideLoading(); }); }
setPagination
setPagination,顾名思义就是更新分页状态的办法,这里有一个潜在的逻辑,当 pageSize 批改的时候,分页要切换为第一页
/** * 更新参数,如果批改的参数是不是 current,重置 current 为 1 * @param pagination */ setPagination(pagination: Partial<Pagination>) {this.setState((s) => { let current = pagination.current || s.pagination.current; if (pagination?.pageSize) {if (pagination.pageSize !== s.pagination.pageSize) {current = 1;} } s.pagination = { ...s.pagination, ...pagination, current, }; }); }
参数设置
上面是更改参数和重置参数的办法
/**
* 更新参数,重置以后申请页面为 1
* @param params
*/
setParams(params: Partial<TableState['params']>) {const d: Partial<TableState['params']> = {};
Object.entries(params).forEach(([k, v]) => {if (v !== undefined) {
Object.assign(d, {[k]: v,
});
}
});
this.setState((s) => {
s.params = {
...s.params,
...d,
};
s.pagination.current = 1;
});
}
resetParams() {this.setState((s) => {s.params = {} as Record<any, any>;
});
}
分页状态批改
很多时候咱们都是用回调函数去监听 ui 组件的分页状态批改,这里也提供一个对应的办法
/**
* 切换页面,并且更新数据
* @param p
*/
onPageChange(p: Pagination) {this.setPagination(p);
return this.updateData();}
残缺的代码例子
残缺的代码例子能够查看 github 仓库,记得给个 star 哈
如何应用
npm install @clean-js/pro-presenters
import React from 'react';
import {usePresenter} from '@clean-js/react-presenter';
import {BaseTablePresenter} from '@clean-js/pro-presenters';
export const demo = () => {const { presenter, state} = usePresenter(BaseTablePresenter);
return (
<Table
loading={state.loading}
columns={state.columns}
pagination={state.pagination}
dataSource={state.data}
onChange={(p) => {presenter.onPageChange?.(p);
}}
/>
);
};
当咱们有多个表格要应用的时候,初始化多个 presenter 即可
上面的两个 usePresenter 会返回不同的实例
import React from 'react';
import {usePresenter} from '@clean-js/react-presenter';
import {BaseTablePresenter} from '@clean-js/pro-presenters';
export const demo = () => {const { presenter, state} = usePresenter(BaseTablePresenter);
const {p: tableP} = usePresenter(BaseTablePresenter);
return (
<div>
<Table
loading={state.loading}
columns={state.columns}
pagination={state.pagination}
dataSource={state.data}
onChange={(p) => {presenter.onPageChange?.(p);
}}
/>
<Table
loading={tableP.state.loading}
columns={tableP.state.columns}
pagination={tableP.state.pagination}
dataSource={tableP.state.data}
onChange={(p) => {tableP.onPageChange?.(p);
}}
/>
</div>
);
};
如何拓展性能
假如咱们须要增加一个 columns 属性,用来配置 UI,咱们能够继承这个 BaseTablePresenter,对其进行扩大即可
type Columns = {key: string}[];
class CustomTableP extends BaseTablePresenter<
{name: string},
{columns: Columns}
> {constructor() {
super({data: [],
loading: false,
params: {},
pagination: {
current: 1,
pageSize: 10,
total: 1,
},
columns: [],});
}
setColumns(columns: Columns) {this.setState((s) => {s.columns = columns;});
}
test() {return 'test';}
}
export const demo = () => {const { presenter, state} = usePresenter(CustomTableP);
return (
<Table
loading={state.loading}
columns={state.columns}
pagination={state.pagination}
dataSource={state.data}
onChange={(p) => {presenter.onPageChange?.(p);
}}
/>
);
};
npm 包地址
github 地址,记得给个 star 哈