今天说说管理后台常用的一个功能。表格功能需求分析首先看下面的表格页面,它有过滤、分页、渲染等功能,根据这些功能,我们可以定义页面视图需要的数据模型。视图数据模型首先与分页相关。数据接口分页{current:number;总数;pageSize:number;}data:每行数据params:请求参数loading:...exportinterfaceTableState{loading:boolean;data:Row[];params:Record;pagination:Pagination&Record;[p:string]:any;}有了这些数据,就可以满足表格的正常渲染了。接下来定义视图操作方法。表需要的操作方法是loadingcontrol这里我们用两个方法来控制loading的切换showLoading(){if(this._loadingCount===0){this.setState((s)=>{s.loading=真的;});}this._loadingCount+=1;}hideLoading(){this._loadingCount-=1;如果(this._loadingCount===0){this.setState((s)=>{s.loading=false;});}}fetchData方法获取数据,这里定义一个异步函数,声明接口定义,函数内容直接抛出错误,需要等待具体使用实现真正的fetchDataasyncfetchData(params:Partial&{current:number;pageSize:number;},):Promise<{data:any[];当前:数量;pageSize:数字;total:number;}>{throwError('PleaseimplementfetchTable');}updateDataupdateData方法用于调用fetchData,更新数据,切换加载/***发送请求,更新数据*@returns*/updateData(){constparams:Record={};Object.entries(this.state.params||{}).forEach(([k,v])=>{if(v!==undefined){Object.assign(params,{[k]:v});}});这个.showLoading();returnthis.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;});返回res;}).finally(()=>{this.hideLoading();});}setPaginationsetPagination,顾名思义,就是更新分页状态的方法。这里有一个潜在的逻辑。当修改pageSize时,分页应该切换到第一页/***更新参数。如果修改的参数不是current,则将current重置为1*@parampagination*/setPagination(pagination:Partial){this.setState((s)=>{letcurrent=pagination.current||s.pagination.current;if(pagination?.pageSize){if(pagination.pageSize!==s.pagination.pageSize){current=1;}}s.pagination={...s.pagination,...pagination,current,};});}参数设置下面是更改参数和重置参数的方法/***更新参数,将当前请求页面重置为1*@paramparams*/setParams(params:Partial){constd:Partial={};Object.entries(params).forEach(([k,v])=>{if(v!==undefined){Object.assign(d,{[k]:v,});}});这个.setState((s)=>{s.params={...s.params,...d,};s.pagination.current=1;});}resetParams(){this.setState((s)=>{s.params={}asRecord;});}分页状态修改很多时候我们使用回调函数来监听ui组件的分页状态修改,这里也提供了相应的方法/***切换页面,以及并更新数据*@paramp*/onPageChange(p:Pagination){this.setPagination(p);返回this.updateData();}完整代码示例可以在github仓库查看完整代码示例,记得给个star怎么样使用npminstall@clean-js/pro-presentersimportReactfrom'react';import{usePresenter}from'@clean-js/react-presenter';从'@clean-js/pro-presenters'导入{BaseTablePresenter};exportconstdemo=()=>{const{presenter,state}=usePresenter(BaseTablePresenter);返回(}}/>);};当我们有多个表要用的时候,初始化多个presenter。下面两个usePresenter会返回不同的实例=()=>{const{presenter,state}=usePresenter(BaseTablePresenter);const{p:tableP}=usePresenter(BaseTablePresenter);return({presenter.onPageChange?.(p);}}/>{tableP.onPageChange?.(p);}}/> );};如何扩展功能假设我们需要添加一个columns属性来配置UI,我们可以继承这个BaseTablePresenter并对其进行扩展。类型Columns={key:string}[];classCustomTablePextendsBaseTablePresenter<{name:string},{columns:Columns}>{constructor(){super({data:[],加载:false,参数:{},分页:{当前:1,pageSize:10,总计:1,},列:[],});}setColumns(columns:Columns){this.setState((s)=>{s.columns=columns;});}测试(){返回“测试”;}}exportconstdemo=()=>{const{presenter,state}=usePresenter(CustomTableP);返回(}}/>);};npm包地址github地址,记得给一个star哈