城市列表(2)长列表渲染

1.长列表(城市列表,通讯录,微博等)大型数据表格会使页面出现卡顿,不流畅等性能问题
原因:大量的Dom重绘重排,或者设备老旧
解决:懒加载,可视区渲染
懒加载:(常用于移动端)
每次只渲染一部分数据,渲染的数据滚动时,在加载剩余部分
数据量不大时可以使用,不然会出现卡顿,不流畅等性能问题、
可视区渲染:(react- virtualized)
只渲染可视区列表的内容,看不见的区域不渲染,滚动列表区域时动态加载数据。
地址链接

安装:npm i react-virtualized
引入:import ‘react-virtualied/style.css’
地址链接

import React from 'react'
import { NavBar, Icon } from 'antd-mobile';
import './index.scss'
import axios from 'axios'
import {getCurrentCity} from '../../utils'
// 导入List组件
import {List, AutoSizer} from 'react-virtualized';


const TITLE_HIGHT = 36
const INDEX_CITY = 50
// 数据格式化方法
    const formatDataCity = (list)=>{
        const cityList = {}
        // const cityIndex = []
        // 1.遍历list数组
        list.forEach(item=>{
            // 2.获取每个城市首字母
            const first= item.short.substr(0,1)
            console.log(first)
            // 3.判断cityList是否有该分类
            if(cityList[first]){
                // 4.如果有就往该分类中push数据
                cityList[first].push(item)
            } else{
                // 5.如果没有就创建新数组存储
                cityList[first] = [item]
            }
        })
        // 获取索引数据
        const cityIndex=Object.keys(cityList).sort()
        return{
            cityList,
            cityIndex
        }


    }
    // 封装处理索引方法
    const formatCityIndex =(letter)=>{
        switch (letter) {
            case '#':
                return '当前定位'
            case 'hot':
                return '热门城市'
        
            default:
                return letter.toUpperCase()
        }
    }
    // 列表数据源
    // const list = Array(100).fill('zujian')
    
export default class CityList extends React.Component{
    constructor(props){
        super(props)
        this.state={
            cityList:{},
            cityIndex:[],
            activeIndex:0
        }
        this.cityListComponent = React.createRef()
    }
    
    async componentDidMount(){
        await this.getCityLists()
        this.cityListComponent.current.measureAllRows()
    }

    // 获取城市列表数据
    async getCityLists(){
        const res = await axios.get('http://localhost:8080/area/city?level=1')
       
       
        console.log(res)
       const{cityList,cityIndex}= formatDataCity(res.data.body)

      
       const hot = await axios.get('http://localhost:8080/area/hot')
       cityList['hot'] = hot.data.body
    //    将索引添加到cityIndex中
        cityIndex.unshift('hot')
        // 获取当前定位城市
        const curCity = await getCurrentCity()
        // 把当前定位城市加到cityList中
        cityList['#'] = [curCity]
        cityIndex.unshift('#')
        console.log(cityList,cityIndex,curCity)
        this.setState({
            cityIndex,
            cityList
        })
       
    }
   // 渲染每一行数据的渲染函数  函数的返回值就是渲染在页面的每一行内容
    rowRenderer=({
        key, // Unique key within array of rows
        index, // Index of row within collection
        isScrolling, // The List is currently being scrolled
        isVisible, // This row is visible within the List (eg it is not an overscanned row)
        style, // Style object to be applied to row (to position it)
        
    })=> {
        const { cityIndex,cityList } = this.state
        const letter = cityIndex[index]
        return (
        <div key={key} style={style} className="city">
            <div className="title">{formatCityIndex(letter)}</div>
            {
                cityList[letter].map((item=><div className="name" key={item.value}>{item.label}</div>))
            }
          
        </div>
        )
    }
    // 动态计算高度
    getRowHight = ({index})=>{
        const {cityList,cityIndex} = this.state
        return TITLE_HIGHT+cityList[cityIndex[index]].length*INDEX_CITY
    }

   // 封装渲染右侧索引列表的方法
  renderCityIndex() {
    // 获取到 cityIndex,并遍历其,实现渲染
    const { cityIndex, activeIndex } = this.state
    return cityIndex.map((item, index) => (
      <li className="city-index-item" key={item} onClick={()=>{
        this.cityListComponent.current.scrollToRow(index)
      }}>
        <span className={activeIndex === index ? 'index-active' : ''}>
          {item === 'hot' ? '热' : item.toUpperCase()}
        </span>
      </li>
    ))
  }
//   用于获取list组件中渲染行的信息
  onRowsRendered=({startIndex})=>{
    if(this.state.activeIndex !== startIndex){
        this.setState({
            activeIndex:startIndex
        })
    }
  }
    
    
   

    render(){
        return (
            <div className="cityList">
                <NavBar
                    mode="light"
                    icon={<i className="iconfont icon-back"/>}
                    onLeftClick={() => this.props.history.go(-1)}
                    >城市列表
                    </NavBar>
                    {/* list组件 */}
                    <AutoSizer>
                        {({height, width}) => (
                        <List
                            ref={this.cityListComponent}
                            height={height}
                            rowCount={this.state.cityIndex.length}
                            rowHeight={this.getRowHight}
                            rowRenderer={this.rowRenderer}
                            width={width}
                            onRowsRendered = {this.onRowsRendered}
                            scrollToAlignment="start"
                        />
                        )}
                    </AutoSizer>
                    <ul className="city-index">
                          {this.renderCityIndex()}  
                    </ul>
            </div>
        )
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值