项目作者: Rahim-Chan

项目描述 :
taro框架长列表方案 :集成下拉刷新、骨架屏、无限滚动、图片懒加载;
高级语言: TypeScript
项目地址: git://github.com/Rahim-Chan/taro-listview.git
创建时间: 2019-07-10T02:00:08Z
项目社区:https://github.com/Rahim-Chan/taro-listview

开源协议:

下载


📦🚀taro-listview


semantic-release

npm latest version

GitHub Actions status

  • 列表内部懒模块-解决小程序图片过多内存问题
  • skeleton 拓展状态屏
  • virtual-list(WIP)【虚拟列表】
  • 支持TaroV3 、NPM版本2.x.x

维护平台

微信小程序h5

文档

Documents

安装方式

安装:npm i taro-listviewyarn add taro-listview

使用案例

引入组件

列表 Demo

!!!需给组件设置固定高度

API

ListView

可配置参数

页面状态控制参数

属性 说明 类型 默认值 必传
style - - - -
lazy 开启懒加载(传入字符串为父元素 className 且开启) boolean or string false or ‘.lazy-view’ -
hasMore 加载更多 boolean true true
isEmpty 展示空凭页 boolean - -
isError 展示错误页 boolean - -
needInit 初始化&自动调用下拉刷新方法 boolean - -
distanceToRefresh 下拉刷新距离 number - -
damping 最大下拉距离 number - -
autoHeight 开启自适应高度 boolean - -
lazyStorage Storage Key值用于区分ListView string box -

自定义页面 UI(状态提示语,空白屏、错误屏、底部状态的 UI 自定义)

属性 说明 类型 默认值 必传
color 下拉加载时 loading 的颜色 string #667baf -
emptyText 空白页提示语 string - -
footerLoadedText 列表底部加载完毕提示语 string -
footerLoadingText 列表底部加载中提示语 string 加载中 -
launch *是否开启状态屏的渲染,状态屏节点对应以下 renderXX 属性(如下) object { launchError = false, launchEmpty = false, launchFooterLoaded = false, launchFooterLoading = false } -
renderError 错误页 Taro.Node - -
renderEmpty 空白页 Taro.Node - -
renderFooterLoaded 自定义底部加载完毕 Taro.Node - -
renderFooterLoading 自定义底部加载 Taro.Node - -
indicator 下拉提示语 Object { release = '加载中', activate = '下拉刷新', deactivate = '释放刷新'} -

*错误屏中重新初始化方法与下拉刷新方法一致

  1. import Taro, { Component } from "@tarojs/taro";
  2. import { View, Image } from "@tarojs/components";
  3. import ListView, { LazyBlock } from "taro-listview";
  4. const blankList = [
  5. {
  6. author: {},
  7. title: "this is a example"
  8. },
  9. {
  10. author: {},
  11. title: "this is a example"
  12. },
  13. {
  14. author: {},
  15. title: "this is a example"
  16. },
  17. {
  18. author: {},
  19. title: "this is a example"
  20. }
  21. ];
  22. let pageIndex = 1;
  23. export default class Index extends Component {
  24. state = {
  25. isLoaded: false,
  26. error: false,
  27. hasMore: true,
  28. isEmpty: false,
  29. list: blankList
  30. };
  31. getData = async (pIndex = pageIndex) => {
  32. if (pIndex === 1) this.setState({ isLoaded: false });
  33. const {
  34. data: { data }
  35. } = await Taro.request({
  36. url: "https://cnodejs.org/api/v1/topics",
  37. data: {
  38. limit: 10,
  39. page: pIndex
  40. }
  41. });
  42. console.log({ data });
  43. return { list: data, hasMore: true, isLoaded: pIndex === 1 };
  44. };
  45. componentDidMount() {
  46. this.refList.fetchInit();
  47. }
  48. pullDownRefresh = async () => {
  49. pageIndex = 1;
  50. const res = await this.getData(1);
  51. this.setState(res);
  52. };
  53. onScrollToLower = async fn => {
  54. const { list } = this.state;
  55. const { list: newList, hasMore } = await this.getData(++pageIndex);
  56. this.setState({
  57. list: list.concat(newList),
  58. hasMore
  59. });
  60. fn();
  61. };
  62. refList = {};
  63. insRef = node => {
  64. this.refList = node;
  65. };
  66. render() {
  67. const { isLoaded, error, hasMore, isEmpty, list } = this.state;
  68. return (
  69. <View className="skeleton lazy-view">
  70. <ListView
  71. lazy
  72. ref={node => this.insRef(node)}
  73. isLoaded={isLoaded}
  74. isError={error}
  75. hasMore={hasMore}
  76. style={{ height: "100vh" }}
  77. isEmpty={isEmpty}
  78. onPullDownRefresh={this.pullDownRefresh}
  79. onScrollToLower={this.onScrollToLower}
  80. lazyStorage='lazyView'
  81. >
  82. {list.map((item, index) => {
  83. return (
  84. <View className="item skeleton-bg" key={index}>
  85. <LazyBlock current={index} className="avatar" lazyStorage='lazyView'>
  86. <Image
  87. className="avatar skeleton-radius"
  88. src={item.author.avatar_url}
  89. ></Image>
  90. </LazyBlock>
  91. <View className="title skeleton-rect">{item.title}</View>
  92. </View>
  93. );
  94. })}
  95. </ListView>
  96. </View>
  97. );
  98. }
  99. }

模块懒加载

1.模块需固定同一高度。

2.只能在 ListView 组件内使用,并开启 lazy 模式,且父元素的 className=’lazy-view’!!!

3.组件需传入模块遍历后的下标。

API

LazyBlock
属性 说明 类型 默认值 必传
current 传入模块遍历后的下标 number null true
lazyStorage Storage Key值用于区分ListView(获取是哪一个ListView) string box -
  1. import Taro, { Component } from "@tarojs/taro";
  2. import { View, Image } from "@tarojs/components";
  3. import ListView, { LazyBlock } from "taro-listView";
  4. let pageIndex = 1;
  5. export default class Index extends Component {
  6. state = {
  7. isLoaded: false,
  8. error: false,
  9. hasMore: true,
  10. isEmpty: false,
  11. list: []
  12. };
  13. getData = async (pIndex = pageIndex) => {
  14. if (pIndex === 1) this.setState({ isLoaded: false });
  15. const {
  16. data: { data }
  17. } = await Taro.request({
  18. url: "https://cnodejs.org/api/v1/topics",
  19. data: {
  20. limit: 10,
  21. page: pIndex
  22. }
  23. });
  24. return { list: data, hasMore: true, isLoaded: pIndex === 1 };
  25. };
  26. componentDidMount() {
  27. this.getData();
  28. }
  29. onScrollToLower = async fn => {
  30. const { list } = this.state;
  31. const { list: newList, hasMore } = await this.getData(++pageIndex);
  32. this.setState({
  33. list: list.concat(newList),
  34. hasMore
  35. });
  36. fn();
  37. };
  38. render() {
  39. const { isLoaded, error, hasMore, isEmpty, list } = this.state;
  40. return (
  41. <View className="lazy-view">
  42. <ListView
  43. lazy
  44. isLoaded={isLoaded}
  45. hasMore={hasMore}
  46. style={{ height: "100vh" }}
  47. onScrollToLower={this.onScrollToLower}
  48. lazyStorage='lazyViewBlock'
  49. >
  50. {list.map((item, index) => {
  51. return (
  52. <View className='item' key={index}>
  53. <LazyBlock current={index} className='avatar' lazyStorage='lazyViewBlock'>
  54. <Image className='avatar' src={item.author.avatar_url} ></Image>
  55. </LazyBlock>
  56. <View className="title">{item.title}</View>
  57. </View>
  58. );
  59. })}
  60. </ListView>
  61. </View>
  62. );
  63. }
  64. }

骨架屏

1.因骨架屏是捕捉已有占位数据的样式,再绘制出骨架,所以要先注入默认空白占位数据。

2.且需要一个传入父元素的 className(默认获取为“skeleton”),以便寻找元素下的所有“关节”元素。可通过传入 selector 参数自定义 className。

  1. 有且只有捕捉以下提供的“关节”样式名:背景('skeleton-bg')、矩阵('skeleton-rect')、圆形('skeleton-redius')。

3.ListView 组件已嵌套 Skeleton 组件,直接调用对应属性即可。

*“关节”元素需内容撑开,或者固定高度。

API

Skeleton
属性 说明 类型 默认值 必传
isLoaded 骨架屏是否显示(eg:加载第一页时开启) boolean false -
selector 骨架屏外层 class 名称 skeleton - -

骨架屏 Demo

  1. import Taro, { useState } from "@tarojs/taro";
  2. import { View, Button } from "@tarojs/components";
  3. import { Skeleton } from "components";
  4. import "./index.scss";
  5. export default () => {
  6. const [isLoaded, setLoaded] = useState(false);
  7. return (
  8. <View>
  9. <Button onClick={() => setLoaded(!isLoaded)}>toggle</Button>
  10. <View className="skeleton">
  11. <Skeleton isLoaded={isLoaded}>
  12. {Array(4)
  13. .fill(1)
  14. .map(i => (
  15. <View className="item skeleton-bg" key={i}>
  16. <View className="avatar skeleton-radius" ></View>
  17. <View className="title skeleton-rect">title</View>
  18. </View>
  19. ))}
  20. </Skeleton>
  21. </View>
  22. </View>
  23. );
  24. };

方法参数

事件名称 说明 类型 默认值 必传
onPullDownRefresh 下拉刷新触发函数 function - -
onScrollToLower 上拉底触发函数 function - -
  1. onPullDownRefresh = () => {
  2. getData();
  3. };
  4. onScrollToLower = async fn => {
  5. await getData();
  6. fn();
  7. };