李优秀 发表于 2025-1-4 11:01:13

React实现长列表

最近学习React,做的小练习
功能:
1,都会列表展示
2,利用索引快速定位相应的都会列表部分,滚动都会列表,索引跟随定位
3,点击都会名称切换都会
https://i-blog.csdnimg.cn/direct/90ac52487bc14c41bf722a2a7765e1b5.gif#pic_center
代码如下:

import React from "react";
import "./index.scss";
import { useNavigate } from "react-router-dom";
import { Toast } from "antd-mobile";
import request from "../../request";
import { getCurrenCity } from "../../utils/index";

import { List, AutoSizer } from "react-virtualized";

import NavHeader from "../../components/NavHeader/index";

export default function Citylist() {
// 索引(A,B……)的高度
const TITLE_HEIGHT = 36;
// 每个城市名称的高度
const NAME_HEIGHT = 50;

// 有房源的城市
const HOUSE_CITY = ["北京", "上海", "广州", "深圳"];

const navigate = useNavigate();
let hotCity = [];
const cityListComponent = React.useRef();
const = React.useState(0);
const = React.useState({});
const = React.useState([]);

// 初始化
React.useEffect(() => {
    getCityList();
    getHotCityList();

    setTimeout(() => {
      cityListComponent.current.measureAllRows();
    }, 1000);
}, []);

// 获取城市列表数据
const getCityList = () => {
    const params = { params: { level: 1 } };
    request.get("/area/city", params).then((res) => {
      if (res.body.length > 0) {
      // console.log("城市列表数据",res.body)
      const { cityList, cityIndex } = formatData(res.body);
      // console.log("数据格式化=》", cityList, cityIndex);
      setCityIndex(cityIndex);
      setCityList(cityList);
      }
    });
};

// 获取热门城市数据
const getHotCityList = () => {
    request.get("/area/hot").then((res) => {
      if (res.body.length > 0) {
      // console.log("热门城市=》", res.body);
      hotCity = res.body;
      }
    });
};

// 格式化城市列表数据
const formatData = (list) => {
    let cityList = {};
    let cityIndex = [];

    // 渲染城市列表的数据格式为:
    // {a:[{},{}],b:[],……}
    list.forEach((item) => {
      const key = item.short.substr(0, 1);
      if (cityList) {
      cityList.push(item);
      } else {
      cityList = ;
      }
    });

    // 渲染右侧索引的数据格式
    // ['a','b',……]
    cityIndex = Object.keys(cityList).sort();

    // 添加热门城市
    cityList["hot"] = hotCity;
    cityIndex.unshift("hot");

    // 添加当前定位城市
    getCurrenCity().then((data) => {
      cityList["#"] = ;
      cityIndex.unshift("#");
    });
    return { cityList, cityIndex };
};

// 格式化城市索引
const formatCityIndex = (letter) => {
    switch (letter) {
      case "#":
      return "当前定位";
      case "hot":
      return "热门城市";
      default:
      return letter.toUpperCase(); // A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    }
};

// 计算每行的高度
const getRowHeight = ({ index }) => {
    const list = cityList];
    return list.length * NAME_HEIGHT + TITLE_HEIGHT;
};

// 渲染索引
const renderIndex = () => {
    return cityIndex.map((item, index) => (
      <li
      key={item}
      className="city-index-item"
      onClick={() => {
          setCurrentIndex(index);
          return cityListComponent.current.scrollToRow(index);
      }}
      >
      <span className={currentIndex === index ? "index-acitve" : ""}>
          {item === "hot" ? "热" : item.toUpperCase()}
      </span>
      </li>
    ));
};

const rowRenderer = ({ key, index, style }) => {
    const letter = cityIndex;
    return (
      <div key={key} style={style} className="city">
      <div className="title">{formatCityIndex(letter)}</div>
      {cityList.map((item) => {
          return (
            <div
            key={item.value}
            className="name"
            onClick={() => changeItem(item)}
            >
            {item.label}
            </div>
          );
      })}
      </div>
    );
};

const changeItem = ({ label, value }) => {
    if (HOUSE_CITY.includes(label)) {
      localStorage.setItem("hkzf_city", JSON.stringify({ label, value }));
      navigate("/home");
    } else {
      Toast.show({
      content: "暂无房源信息",
      });
    }
};
const onRowsRendered = ({ startIndex }) => {
    if (startIndex !== currentIndex) {
      setCurrentIndex(startIndex);
    }
};

return (
    <div className="cityList_main">
      <NavHeader title="城市选择" />

      <AutoSizer>
      {({ height, width }) => (
          <List
            ref={cityListComponent}
            width={width}
            height={height}
            rowCount={cityIndex.length}
            rowHeight={getRowHeight}
            rowRenderer={rowRenderer}
            onRowsRendered={onRowsRendered}
            scrollToAlignment="start"
          />
      )}
      </AutoSizer>

      <ul className="city-index">{renderIndex()}</ul>
    </div>
);
}

   相干视频:https://www.bilibili.com/video/BV1gh411U7JD?spm_id_from=333.788.videopod.episodes&vd_source=2f48f471bbeafdcd207f29dadcc97a5d&p=131

gitee地址:https://gitee.com/abcdfdewrw/react_hkzf

第三方组件:react-virtualized长列表

难点:数据格式处置惩罚,react-virtualized组件在项目中的利用

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: React实现长列表