{"id":13836797,"url":"https://github.com/Rahim-Chan/taro-listview","last_synced_at":"2025-07-10T16:30:51.387Z","repository":{"id":35011472,"uuid":"196112209","full_name":"Rahim-Chan/taro-listview","owner":"Rahim-Chan","description":"taro框架长列表方案 ：集成下拉刷新、骨架屏、无限滚动、图片懒加载；","archived":false,"fork":false,"pushed_at":"2023-01-26T23:42:00.000Z","size":2481,"stargazers_count":299,"open_issues_count":21,"forks_count":59,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-08-09T03:09:11.089Z","etag":null,"topics":["lazyload","npm","skeleton","taro","taro-listview","virtual-listview"],"latest_commit_sha":null,"homepage":"https://taro-listview-docs-aqi1r3dhf.vercel.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rahim-Chan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-10T02:00:08.000Z","updated_at":"2024-06-27T23:56:20.000Z","dependencies_parsed_at":"2023-02-15T03:02:03.159Z","dependency_job_id":null,"html_url":"https://github.com/Rahim-Chan/taro-listview","commit_stats":null,"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rahim-Chan%2Ftaro-listview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rahim-Chan%2Ftaro-listview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rahim-Chan%2Ftaro-listview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rahim-Chan%2Ftaro-listview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rahim-Chan","download_url":"https://codeload.github.com/Rahim-Chan/taro-listview/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225647787,"owners_count":17502130,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lazyload","npm","skeleton","taro","taro-listview","virtual-listview"],"created_at":"2024-08-04T15:00:54.663Z","updated_at":"2024-11-20T23:31:46.256Z","avatar_url":"https://github.com/Rahim-Chan.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003ch1 align=\"center\" style=\"border-bottom: none;\"\u003e📦🚀taro-listview\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n\u003cimg alt=\"semantic-release\" src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\"\u003e\n\u003ca href=\"https://www.npmjs.com/package/taro-listview\"\u003e\n  \u003cimg alt=\"npm latest version\" src=\"https://img.shields.io/npm/v/taro-listview/latest.svg\"\u003e\n\u003c/a\u003e\n\u003cimg alt=\"GitHub Actions status\" src=\"https://github.com/actions/toolkit/workflows/Main%20workflow/badge.svg\" style=\"max-width:100%;\"\u003e\n\u003c/p\u003e\n\n\n- [x] 列表内部懒模块-解决小程序图片过多内存问题\n- [ ] skeleton 拓展状态屏\n- [ ] virtual-list(WIP)【虚拟列表】\n- [x] 支持TaroV3 、NPM版本2.x.x\n\n## 维护平台\n`微信小程序`、`h5`\n\n## 文档\n[Documents](https://taro-listview-docs-aqi1r3dhf.vercel.app/)\n\n## 安装方式\n\n\u003e 安装：`npm i taro-listview`，`yarn add taro-listview`\n\n## 使用案例\n\n### 引入组件\n\n[列表 Demo](https://github.com/Rahim-Chan/taro-listview/blob/master/src/pages/index/index.tsx)\n\n!!!需给组件设置固定高度\n\n### API\n\n#### ListView\n\n## 可配置参数\n\n### 页面状态控制参数\n\n| 属性              | 说明                                            | 类型              | 默认值                | 必传 |\n| :---------------- | :---------------------------------------------- | :---------------- | :-------------------- | :--- |\n| style             | -                                               | -                 | -                     | -    |\n| lazy              | 开启懒加载(传入字符串为父元素 className 且开启) | boolean or string | false or '.lazy-view' | -    |\n| hasMore           | 加载更多                                        | boolean           | true                  | true |\n| isEmpty           | 展示空凭页                                      | boolean           | -                     | -    |\n| isError           | 展示错误页                                      | boolean           | -                     | -    |\n| needInit          | 初始化\u0026自动调用下拉刷新方法                     | boolean           | -                     | -    |\n| distanceToRefresh | 下拉刷新距离                                    | number            | -                     | -    |\n| damping           | 最大下拉距离                                    | number            | -                     | -    |\n| autoHeight        | 开启自适应高度                                  | boolean           | -                     | -    |\n| lazyStorage       | Storage Key值用于区分ListView                  | string            | box                   | -    |\n\n### 自定义页面 UI（状态提示语，空白屏、错误屏、底部状态的 UI 自定义）\n\n| 属性                | 说明                                                             | 类型      | 默认值                                                                                                  | 必传 |\n| :------------------ | :--------------------------------------------------------------- | :-------- | :------------------------------------------------------------------------------------------------------ | :--- |\n| color               | 下拉加载时 loading 的颜色                                        | string    | #667baf                                                                                                 | -    |\n| emptyText           | 空白页提示语                                                     | string    | -                                                                                                       | -    |\n| footerLoadedText        | 列表底部加载完毕提示语                                                   | string    | -                                                                                                       |\n| footerLoadingText       | 列表底部加载中提示语                                                   | string    | 加载中                                                                                                  | -    |\n| launch              | \\*是否开启状态屏的渲染，状态屏节点对应以下 renderXX 属性（如下） | object    | `{ launchError = false, launchEmpty = false, launchFooterLoaded = false, launchFooterLoading = false }` | -    |\n| renderError         | 错误页                                                           | Taro.Node | -                                                                                                       | -    |\n| renderEmpty         | 空白页                                                           | Taro.Node | -                                                                                                       | -    |\n| renderFooterLoaded  | 自定义底部加载完毕                                               | Taro.Node | -                                                                                                       | -    |\n| renderFooterLoading | 自定义底部加载                                                   | Taro.Node | -                                                                                                       | -    |\n| indicator           | 下拉提示语                                                       | Object    | `{ release = '加载中', activate = '下拉刷新', deactivate = '释放刷新'}`                                 | -    |\n\n\\*错误屏中重新初始化方法与下拉刷新方法一致\n\n```jsx\nimport Taro, { Component } from \"@tarojs/taro\";\nimport { View, Image } from \"@tarojs/components\";\nimport ListView, { LazyBlock } from \"taro-listview\";\n\nconst blankList = [\n  {\n    author: {},\n    title: \"this is a example\"\n  },\n  {\n    author: {},\n    title: \"this is a example\"\n  },\n  {\n    author: {},\n    title: \"this is a example\"\n  },\n  {\n    author: {},\n    title: \"this is a example\"\n  }\n];\n\nlet pageIndex = 1;\n\nexport default class Index extends Component {\n  state = {\n    isLoaded: false,\n    error: false,\n    hasMore: true,\n    isEmpty: false,\n    list: blankList\n  };\n\n  getData = async (pIndex = pageIndex) =\u003e {\n    if (pIndex === 1) this.setState({ isLoaded: false });\n    const {\n      data: { data }\n    } = await Taro.request({\n      url: \"https://cnodejs.org/api/v1/topics\",\n      data: {\n        limit: 10,\n        page: pIndex\n      }\n    });\n    console.log({ data });\n    return { list: data, hasMore: true, isLoaded: pIndex === 1 };\n  };\n\n  componentDidMount() {\n    this.refList.fetchInit();\n  }\n\n  pullDownRefresh = async () =\u003e {\n    pageIndex = 1;\n    const res = await this.getData(1);\n    this.setState(res);\n  };\n\n  onScrollToLower = async fn =\u003e {\n    const { list } = this.state;\n    const { list: newList, hasMore } = await this.getData(++pageIndex);\n    this.setState({\n      list: list.concat(newList),\n      hasMore\n    });\n    fn();\n  };\n\n  refList = {};\n\n  insRef = node =\u003e {\n    this.refList = node;\n  };\n\n  render() {\n    const { isLoaded, error, hasMore, isEmpty, list } = this.state;\n    return (\n      \u003cView className=\"skeleton lazy-view\"\u003e\n        \u003cListView\n          lazy\n          ref={node =\u003e this.insRef(node)}\n          isLoaded={isLoaded}\n          isError={error}\n          hasMore={hasMore}\n          style={{ height: \"100vh\" }}\n          isEmpty={isEmpty}\n          onPullDownRefresh={this.pullDownRefresh}\n          onScrollToLower={this.onScrollToLower}\n          lazyStorage='lazyView'\n        \u003e\n          {list.map((item, index) =\u003e {\n            return (\n              \u003cView className=\"item skeleton-bg\" key={index}\u003e\n                \u003cLazyBlock current={index} className=\"avatar\" lazyStorage='lazyView'\u003e\n                  \u003cImage\n                    className=\"avatar skeleton-radius\"\n                    src={item.author.avatar_url}\n                  /\u003e\n                \u003c/LazyBlock\u003e\n                \u003cView className=\"title skeleton-rect\"\u003e{item.title}\u003c/View\u003e\n              \u003c/View\u003e\n            );\n          })}\n        \u003c/ListView\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\n### 模块懒加载\n\n1.模块需固定同一高度。\n\n2.只能在 ListView 组件内使用，并开启 lazy 模式，且父元素的 className='lazy-view'!!!\n\n3.组件需传入模块遍历后的下标。\n\n#### API\n\n##### LazyBlock\n| 属性 | 说明                | 类型   |默认值   |必传   |\n| :------- | :---------------  | :--------- |:--------- |:--------- |\n| current   | 传入模块遍历后的下标    | number | null | true |\n| lazyStorage   | Storage Key值用于区分ListView(获取是哪一个ListView)    | string | box | - |\n\n```jsx\nimport Taro, { Component } from \"@tarojs/taro\";\nimport { View, Image } from \"@tarojs/components\";\nimport ListView, { LazyBlock } from \"taro-listView\";\n\nlet pageIndex = 1;\n\nexport default class Index extends Component {\n  state = {\n    isLoaded: false,\n    error: false,\n    hasMore: true,\n    isEmpty: false,\n    list: []\n  };\n\n  getData = async (pIndex = pageIndex) =\u003e {\n    if (pIndex === 1) this.setState({ isLoaded: false });\n    const {\n      data: { data }\n    } = await Taro.request({\n      url: \"https://cnodejs.org/api/v1/topics\",\n      data: {\n        limit: 10,\n        page: pIndex\n      }\n    });\n    return { list: data, hasMore: true, isLoaded: pIndex === 1 };\n  };\n\n  componentDidMount() {\n    this.getData();\n  }\n\n  onScrollToLower = async fn =\u003e {\n    const { list } = this.state;\n    const { list: newList, hasMore } = await this.getData(++pageIndex);\n    this.setState({\n      list: list.concat(newList),\n      hasMore\n    });\n    fn();\n  };\n\n  render() {\n    const { isLoaded, error, hasMore, isEmpty, list } = this.state;\n    return (\n      \u003cView className=\"lazy-view\"\u003e\n        \u003cListView\n          lazy\n          isLoaded={isLoaded}\n          hasMore={hasMore}\n          style={{ height: \"100vh\" }}\n          onScrollToLower={this.onScrollToLower}\n          lazyStorage='lazyViewBlock'\n        \u003e\n          {list.map((item, index) =\u003e {\n            return (\n              \u003cView className='item' key={index}\u003e\n                \u003cLazyBlock current={index} className='avatar' lazyStorage='lazyViewBlock'\u003e\n                  \u003cImage className='avatar' src={item.author.avatar_url} /\u003e\n                \u003c/LazyBlock\u003e\n                \u003cView className=\"title\"\u003e{item.title}\u003c/View\u003e\n              \u003c/View\u003e\n            );\n          })}\n        \u003c/ListView\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\n### 骨架屏\n\n1.因骨架屏是捕捉已有占位数据的样式，再绘制出骨架，所以要先注入默认空白占位数据。\n\n2.且需要一个传入父元素的 className(默认获取为“skeleton”），以便寻找元素下的所有“关节”元素。可通过传入 selector 参数自定义 className。\n\n    有且只有捕捉以下提供的“关节”样式名：背景（'skeleton-bg'）、矩阵（'skeleton-rect'）、圆形（'skeleton-redius'）。\n\n3.ListView 组件已嵌套 Skeleton 组件，直接调用对应属性即可。\n\n\\*“关节”元素需内容撑开，或者固定高度。\n\n#### API\n\n##### Skeleton\n\n| 属性     | 说明                                  | 类型     | 默认值 | 必传 |\n| :------- | :------------------------------------ | :------- | :----- | :--- |\n| isLoaded | 骨架屏是否显示（eg:加载第一页时开启） | boolean  | false  | -    |\n| selector | 骨架屏外层 class 名称                 | skeleton | -      | -    |\n\n[骨架屏 Demo](https://github.com/Rahim-Chan/taro-listview/blob/master/src/pages/skeleton/index.tsx)\n\n```jsx\nimport Taro, { useState } from \"@tarojs/taro\";\nimport { View, Button } from \"@tarojs/components\";\nimport { Skeleton } from \"components\";\nimport \"./index.scss\";\n\nexport default () =\u003e {\n  const [isLoaded, setLoaded] = useState(false);\n  return (\n    \u003cView\u003e\n      \u003cButton onClick={() =\u003e setLoaded(!isLoaded)}\u003etoggle\u003c/Button\u003e\n      \u003cView className=\"skeleton\"\u003e\n        \u003cSkeleton isLoaded={isLoaded}\u003e\n          {Array(4)\n            .fill(1)\n            .map(i =\u003e (\n              \u003cView className=\"item skeleton-bg\" key={i}\u003e\n                \u003cView className=\"avatar skeleton-radius\" /\u003e\n                \u003cView className=\"title skeleton-rect\"\u003etitle\u003c/View\u003e\n              \u003c/View\u003e\n            ))}\n        \u003c/Skeleton\u003e\n      \u003c/View\u003e\n    \u003c/View\u003e\n  );\n};\n```\n\n### 方法参数\n\n| 事件名称          | 说明             | 类型     | 默认值 | 必传 |\n| :---------------- | :--------------- | :------- | :----- | :--- |\n| onPullDownRefresh | 下拉刷新触发函数 | function | -      | -    |\n| onScrollToLower   | 上拉底触发函数   | function | -      | -    |\n\n```jsx\nonPullDownRefresh = () =\u003e {\n  getData();\n};\n\nonScrollToLower = async fn =\u003e {\n  await getData();\n  fn();\n};\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRahim-Chan%2Ftaro-listview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRahim-Chan%2Ftaro-listview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRahim-Chan%2Ftaro-listview/lists"}