react列表渲染技巧
作者: - 时间:2018年08月15日 11:11:16 - 阅读:3 - 评论:0
列表是很常见的需求,所以对于列表的渲染、加载以及相关优化的范式也是越来越多,像滚动加载,函数节流,分时函数等等。就好像对于一个列表来说,它的优化的话题总是能让开发者津津乐道,细细品味。
今天也记录一个对于数据驱动的方式实现的列表的渲染方式。
说说以往我自己对于列表的渲染方法,如react,在state对象中定义一个数组state变量,然后根据接口请求一次就往该数组中填充一次。怎么填充?
//1、你可以直接通过this.setState
this.setState({
list: [...this.state.list, newlist]
})
//newlist是你请求接口获取的数据,当然这个数据是要你处理过的然后符合页面使用的
//2、也可以先把直接操作数组,然后再setState
newlist.forEach((v) => {
this.state.list.push(v);
});
this.setState({}) //是的,可以这么用
这种方式我一直以来都觉得还好,直到要更新的时候,才发现并不是那么的完美。那什么时候需要更新数据呢?打个比方说,这个列表的某些列可能会有取消的按钮,说明点击之后就会改变这一列在数据库中的状态字段,状态字段改变自然也要同步到前端页面,那么前端页面以这种方式保存的数据就要全部推掉然后在接口中填充新的请求数据,这个新的填充数据还必须要从第一页开始,因为列表都是有滚动加载的,这个时候你分不清楚到底是哪一页,所以不得不这样做。
这种方式归根到底的问题在于不能够准确推算当前这个有取消按钮的列是属于哪一页,但如果细想一下就会发现二维数组是很方便区分页数的。
//懒得写demo,直接写之前项目中的实现
async getOrderList( status, tabs_index, page_num ) {
const _source = getQueryString('source');
console.log(page_num)
const result = await func[`${ _source }OrderList`]( status, page_num || this.state.tabs_type[`tab_${ tabs_index }`].page_num );
const _data_name = _source == 'jinpo' ? 'orderList' : 'data';
const result_page = result.page;
const list_data = await result[`${ _data_name }`].map(( value ) => {
return (
<div className="list">
<div className="head">
<span>订单编号:{ value.order_number }</span>
{
this.setOrderType( value, _source )
}
</div>
{
this.setOrderMsg( value, _source )
}
{
(this.getStatus( value ) == '待支付' || this.getStatus( value ) == '待付款' || ( _source != 'jinpo' && this.getStatus( value ) == '待审核' ) ) && <div className="btnBox">
{
(this.getStatus( value ) == '待支付' || this.getStatus( value ) == '待付款' )&& <BigBtn width="1.3" height="0.6" onClick={() => {
this.props.savePayParams({
order_number: value.order_number,
order_numbers: _source == 'jinpo' ? value.order_uuid : value.order_number,
total_amount: this.getPrice(value, _source),
order_type: _source,
notify_url: NOTIFY_URL,
check_route: `/${ _source }OrderDetail?order_number=${ _source == 'jinpo' ? value.order_uuid : value.order_number }`
});
this.props.history.push('/payOrder');
}}>支付</BigBtn>
}
{
_source != 'other' && ( this.getStatus( value ) == '待支付' || this.getStatus( value ) == '待付款' || ( _source != 'jinpo' && this.getStatus( value ) == '待审核' ) ) && <BigBtn border width="1.3" height="0.6" onClick={() => {
Modal.alert('取消订单', '是否要取消订单?', [
{ text: '取消' },
{ text: '确定', onPress: async () => {
if ( getQueryString('source') == 'jinpo' ) {
const __result = await cancelPerorder( value.order_uuid, value.order_number );
Toast.info(__result.msg);
if ( __result.status ) {
this.getOrderList( status, tabs_index, result_page );
}
} else {
const __result = await cancelServiceOrder( value.id );
Toast.info(__result.msg);
if ( __result.status ) {
this.getOrderList( status, tabs_index, result_page );
}
}
}},
])
}}>取消</BigBtn>
}
{
(_source == 'other' && this.getStatus( value ) == '待付款') && <BigBtn border width="1.3" height="0.6" onClick={() => {
Modal.alert('金额错误', '是否确定金额错误?', [
{ text: '取消' },
{ text: '确定', onPress: async () => {
const result = await confirmErrorMoney( value.order_number );
Toast.info(result.msg);
if ( result.status ) {
window.location.reload();
}
}},
])
}}>金额错误</BigBtn>
}
</div>
}
</div>
);
});
if ( page_num ) {
this.state[`tab_${ tabs_index }`][ page_num - 1 ] = list_data;
this.setState({});
} else {
this.state[`tab_${ tabs_index }`][ this.state.tabs_type[`tab_${ tabs_index }`].page_num - 1 ] = list_data;
this.setState({});
result[`${ _data_name }`].length < ORDER_PAGE_NUM && (this.state.tabs_type[`tab_${ tabs_index }`].hasMore = false) || this.state.tabs_type[`tab_${ tabs_index }`].page_num++;
}
}