实现react懒渲染

react 列表懒渲染

使用 react-virtualized 实现

使用步骤:

  • 使用npm进行安装

    npm install react-virtualized
    
  • 引入它的 css 样式文件

    import '../node_modules/react-virtualized/styles.css'
    
  • 使用Link和AutoSizer 组件实现,懒渲染

    import { List, AutoSizer } from 'react-virtualized'
    
  • List 组件的使用
    内置方法:

    • scrollToRow(方法)
      这个方法传入索引值,他会查找传入索引的行,显示到页面可视区域,结合页面索引点击快速导航使用
    • scrollToAlignment(属性)
      结合上个方法,当页面可视区更新时,显示到最顶部还是底部还是居中
      他有四个值可选:start 最上面、center居中、end最底部、auto默认自适应

    如果想要调用他的内置方法必须使用ref获取它(List组件)

    import React from 'react'
    // 使用react创建一个ref
    this.ListRef = React.createRef()
    
    // 因为当前height值和width值不确定,所以要使用AutoSizer组件来获取当前窗体的宽高。
    <AutoSizer>{({width,height})=>{
    		// 将List组件放在这个组件里面
    	<List 
    		ref={ListRef}
    		height={height}    //设置整个列表的高度
    		width={width}    	// 设置整个列表的宽度
    		rowHight={100}		//设置每行的宽度(每循环一个单位的高度),可以是一个变量,也可以是一个函数去计算每行的高度,一般使用函数计算好return 回来一个变量
    		rowCount={}		//  设置循环生成次数(多少行)
            rowRenderer={}  //  渲染每行的dom,值为函数,函数中有一个参数,是一个对象,对象中包含当前索引(index),随机生成的key值,和style样式,循环时必须要加入style样式,否则设置的样式属性不生效
            onRowsRendered={}   // 绑定一个函数,只要列表滚动就会触发这个函数,并且有一个参数,参数里面有当前最上面渲染的元素索引。
            scrollToAlignment="start"  
    	/>
    }}</AutoSizer>
    
    
    
    

完整代码

import React, { PureComponent } from "react";
import { getCityHot, getCityList } from "../../api/home";
import getPosition from "../../utils/GetPosition";
// import { NavBar, Icon } from 'antd-mobile'
import { List, AutoSizer } from 'react-virtualized'
import NavBar from '../../components/Navbar'
import '../../components/TabBar/css/iconfont.css'
import './index.scss'
const TITLE_HEIGHT = 30
const CITY_ITEM_HEIGHT = 45
export default class CityList extends PureComponent {
  constructor() {
    super()
    this.Refs = React.createRef()
  }
  state = {
    CityGroupList: {},
    CityGroupIndex: [],
    currentCity: {},
    CityIndexselect: 0
  }
  render () {
    return (
      <div className="CityList">
        {/* 头部导航部分 */}
        <div className='NavBar'>
          <NavBar ReturnPage={() => { this.props.history.go(-1) }}>选择城市</NavBar>
        </div>
        <AutoSizer>
          {({ width, height }) => {
            return (
              <List
                ref={this.Refs}
                height={height}
                width={width}
                rowHeight={this.getHight}
                rowCount={this.state.CityGroupIndex.length}
                rowRenderer={this.renderCityList}
                onRowsRendered={this.rowsRundered.bind(this)}
                scrollToAlignment="start"
              />
            )
          }}
        </AutoSizer>
        <div className="CityIndexNav">
          <ul>
            {
              this.renderCityIndexNav()
            }
          </ul>
        </div>
      </div>
    )
  }
  async componentDidMount () {
    await this.setCityGroup()
    this.Refs.current.measureAllRows()
  }
  rowsRundered ({ startIndex }) {
    // console.log(startIndex)
    this.setState({
      CityIndexselect: startIndex
    })
  }
  // 懒渲染所有城市
  renderCityList = ({
    key,
    index,
    style
  }) => {
    let cityIndex = this.state.CityGroupIndex[index]
    let citys = this.state.CityGroupList[cityIndex]
    return (
      <div className='indexItem' key={key} style={style}>
        <div className="title">
          {this.renderCityIndex(cityIndex)}
        </div>
        <div className="content">
          {this.renderCityItem(citys, cityIndex)}
        </div>
      </div>
    )
  }
  // 城市索引点击设置选中状态
  CityIndexActive (index) {
    this.Refs.current.scrollToRow(index)
    this.setState({
      CityIndexselect: index
    })
  }
  // 渲染城市索引导航列表
  renderCityIndexNav () {
    return this.state.CityGroupIndex.map((item, index) => {
      return <li onClick={this.CityIndexActive.bind(this, index)} className={this.state.CityIndexselect === index ? 'CityActive' : ''} key={item}>{item === 'hot' ? '热' : item.toUpperCase()}</li>
    })
  }
  // 渲染某个城市索引
  renderCityIndex (cityIndex) {
    if (cityIndex === "#") return <span className='special-title'>当前城市</span>
    if (cityIndex === 'hot') return <span className='special-title'>热门城市</span>
    return cityIndex.toUpperCase()
  }
  // 渲染每个索引下的所有城市
  renderCityItem (citys, cityIndex) {
    if (cityIndex === '#') {
      return (<div className="current-city">
        <div className="currentPositionIcon">
          <span className="iconfont icon-location"></span>
          <span>{citys[0].label}</span>
        </div>
        <div className="RefreshIcon">
          <span className="iconfont icon-shuaxin"></span>
        </div>
      </div>)
    }
    return citys.map(item => {
      return (
        <div onClick={this.selectCity.bind(this, item)} key={item.value} className='city-item'>{item.label}</div>
      )
    })
  }
  // 选择城市
  selectCity ({ label, value }) {
    sessionStorage.setItem('51_home', JSON.stringify({ label, value }))
    this.props.history.push('/')
  }
  // 获取每行的高度
  getHight = ({ index }) => {
    // console.log(this.state.CityGroupList[])
    // return index
    let cityIndex = this.state.CityGroupIndex[index]
    return TITLE_HEIGHT + this.state.CityGroupList[cityIndex].length * CITY_ITEM_HEIGHT
  }
  // 格式化城市数据,城市列表和城市首字母索引,和热门城市,整合成一个对象
  async setCityGroup () {
    const currentCity = await getPosition()
    const { data: { body: CityList } } = await getCityList()
    const { data: { body: CityHot } } = await getCityHot()
    let CityGroupList = {}
    CityList.forEach(item => {
      if (CityGroupList[item.short[0]]) {
        CityGroupList[item.short[0]].push(item)
      } else {
        CityGroupList[item.short[0]] = [item]
      }
    });
    const CityGroupIndex = Object.keys(CityGroupList).sort()
    CityGroupIndex.unshift('hot')
    CityGroupIndex.unshift('#')
    CityGroupList['#'] = [currentCity]
    CityGroupList['hot'] = CityHot
    await this.setState({
      CityGroupIndex,
      CityGroupList,
      currentCity,

    })
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

要爆炸的臭臭君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值