React实现长列表

打印 上一主题 下一主题

主题 1379|帖子 1379|积分 4137

最近学习React,做的小练习
功能:
1,都会列表展示
2,利用索引快速定位相应的都会列表部分,滚动都会列表,索引跟随定位
3,点击都会名称切换都会
  

代码如下:

  1. import React from "react";
  2. import "./index.scss";
  3. import { useNavigate } from "react-router-dom";
  4. import { Toast } from "antd-mobile";
  5. import request from "../../request";
  6. import { getCurrenCity } from "../../utils/index";
  7. import { List, AutoSizer } from "react-virtualized";
  8. import NavHeader from "../../components/NavHeader/index";
  9. export default function Citylist() {
  10.   // 索引(A,B……)的高度
  11.   const TITLE_HEIGHT = 36;
  12.   // 每个城市名称的高度
  13.   const NAME_HEIGHT = 50;
  14.   // 有房源的城市
  15.   const HOUSE_CITY = ["北京", "上海", "广州", "深圳"];
  16.   const navigate = useNavigate();
  17.   let hotCity = [];
  18.   const cityListComponent = React.useRef();
  19.   const [currentIndex, setCurrentIndex] = React.useState(0);
  20.   const [cityList, setCityList] = React.useState({});
  21.   const [cityIndex, setCityIndex] = React.useState([]);
  22.   // 初始化
  23.   React.useEffect(() => {
  24.     getCityList();
  25.     getHotCityList();
  26.     setTimeout(() => {
  27.       cityListComponent.current.measureAllRows();
  28.     }, 1000);
  29.   }, []);
  30.   // 获取城市列表数据
  31.   const getCityList = () => {
  32.     const params = { params: { level: 1 } };
  33.     request.get("/area/city", params).then((res) => {
  34.       if (res.body.length > 0) {
  35.         // console.log("城市列表数据",res.body)
  36.         const { cityList, cityIndex } = formatData(res.body);
  37.         // console.log("数据格式化=》", cityList, cityIndex);
  38.         setCityIndex(cityIndex);
  39.         setCityList(cityList);
  40.       }
  41.     });
  42.   };
  43.   // 获取热门城市数据
  44.   const getHotCityList = () => {
  45.     request.get("/area/hot").then((res) => {
  46.       if (res.body.length > 0) {
  47.         // console.log("热门城市=》", res.body);
  48.         hotCity = res.body;
  49.       }
  50.     });
  51.   };
  52.   // 格式化城市列表数据
  53.   const formatData = (list) => {
  54.     let cityList = {};
  55.     let cityIndex = [];
  56.     // 渲染城市列表的数据格式为:
  57.     // {a:[{},{}],b:[],……}
  58.     list.forEach((item) => {
  59.       const key = item.short.substr(0, 1);
  60.       if (cityList[key]) {
  61.         cityList[key].push(item);
  62.       } else {
  63.         cityList[key] = [item];
  64.       }
  65.     });
  66.     // 渲染右侧索引的数据格式
  67.     // ['a','b',……]
  68.     cityIndex = Object.keys(cityList).sort();
  69.     // 添加热门城市
  70.     cityList["hot"] = hotCity;
  71.     cityIndex.unshift("hot");
  72.     // 添加当前定位城市
  73.     getCurrenCity().then((data) => {
  74.       cityList["#"] = [data];
  75.       cityIndex.unshift("#");
  76.     });
  77.     return { cityList, cityIndex };
  78.   };
  79.   // 格式化城市索引
  80.   const formatCityIndex = (letter) => {
  81.     switch (letter) {
  82.       case "#":
  83.         return "当前定位";
  84.       case "hot":
  85.         return "热门城市";
  86.       default:
  87.         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
  88.     }
  89.   };
  90.   // 计算每行的高度
  91.   const getRowHeight = ({ index }) => {
  92.     const list = cityList[cityIndex[index]];
  93.     return list.length * NAME_HEIGHT + TITLE_HEIGHT;
  94.   };
  95.   // 渲染索引
  96.   const renderIndex = () => {
  97.     return cityIndex.map((item, index) => (
  98.       <li
  99.         key={item}
  100.         className="city-index-item"
  101.         onClick={() => {
  102.           setCurrentIndex(index);
  103.           return cityListComponent.current.scrollToRow(index);
  104.         }}
  105.       >
  106.         <span className={currentIndex === index ? "index-acitve" : ""}>
  107.           {item === "hot" ? "热" : item.toUpperCase()}
  108.         </span>
  109.       </li>
  110.     ));
  111.   };
  112.   const rowRenderer = ({ key, index, style }) => {
  113.     const letter = cityIndex[index];
  114.     return (
  115.       <div key={key} style={style} className="city">
  116.         <div className="title">{formatCityIndex(letter)}</div>
  117.         {cityList[letter].map((item) => {
  118.           return (
  119.             <div
  120.               key={item.value}
  121.               className="name"
  122.               onClick={() => changeItem(item)}
  123.             >
  124.               {item.label}
  125.             </div>
  126.           );
  127.         })}
  128.       </div>
  129.     );
  130.   };
  131.   const changeItem = ({ label, value }) => {
  132.     if (HOUSE_CITY.includes(label)) {
  133.       localStorage.setItem("hkzf_city", JSON.stringify({ label, value }));
  134.       navigate("/home");
  135.     } else {
  136.       Toast.show({
  137.         content: "暂无房源信息",
  138.       });
  139.     }
  140.   };
  141.   const onRowsRendered = ({ startIndex }) => {
  142.     if (startIndex !== currentIndex) {
  143.       setCurrentIndex(startIndex);
  144.     }
  145.   };
  146.   return (
  147.     <div className="cityList_main">
  148.       <NavHeader title="城市选择" />
  149.       <AutoSizer>
  150.         {({ height, width }) => (
  151.           <List
  152.             ref={cityListComponent}
  153.             width={width}
  154.             height={height}
  155.             rowCount={cityIndex.length}
  156.             rowHeight={getRowHeight}
  157.             rowRenderer={rowRenderer}
  158.             onRowsRendered={onRowsRendered}
  159.             scrollToAlignment="start"
  160.           />
  161.         )}
  162.       </AutoSizer>
  163.       <ul className="city-index">{renderIndex()}</ul>
  164.     </div>
  165.   );
  166. }
复制代码
  相干视频: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企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

李优秀

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表