From 1b18b86bbf1b29a9fba337c9905b0395d8a072af Mon Sep 17 00:00:00 2001
From: Tevin <tingquanren@163.com>
Date: Mon, 14 Dec 2020 14:22:42 +0800
Subject: [PATCH] 实现无限滚动

---
 forms/textarea/cTextArea.scss               |    2 
 plugins/infiniteScroll/cInfiniteScroll.scss |   19 ++++++
 plugins/infiniteScroll/index.js             |   10 +++
 plugins/infiniteScroll/CInfiniteScroll.vue  |  128 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 158 insertions(+), 1 deletions(-)

diff --git a/forms/textarea/cTextArea.scss b/forms/textarea/cTextArea.scss
index e66883e..9a368d7 100644
--- a/forms/textarea/cTextArea.scss
+++ b/forms/textarea/cTextArea.scss
@@ -1,5 +1,5 @@
 /**
- * image picker
+ * textarea
  * @author Tevin
  */
 
diff --git a/plugins/infiniteScroll/CInfiniteScroll.vue b/plugins/infiniteScroll/CInfiniteScroll.vue
new file mode 100644
index 0000000..b66a703
--- /dev/null
+++ b/plugins/infiniteScroll/CInfiniteScroll.vue
@@ -0,0 +1,128 @@
+/**
+ * CInfiniteScroll
+ * @author Tevin
+ */
+
+<template>
+    <scroll-view
+        class="c-infinite-scroll"
+        :scrollY="true"
+        @scroll="evt=>onScroll(evt)"
+    >
+        <slot />
+        <view class="bottom">
+            <view v-if="loading">加载中,请稍后...</view>
+            <view v-if="ending">
+                <text v-if="pageTatal > 0">-- 没有更多了 --</text>
+                <text
+                    class="empty"
+                    v-else
+                >暂无数据...</text>
+            </view>
+        </view>
+    </scroll-view>
+</template>
+
+<script>
+import { AtActivityIndicator } from 'taro-ui-vue';
+import './cInfiniteScroll.scss';
+
+export default {
+    name: 'CInfiniteScroll',
+    components: {
+        AtActivityIndicator,
+    },
+    props: {
+        autoInit: {
+            type: Boolean,
+            default: false,
+        },
+        onLoadMore: Function,
+    },
+    data() {
+        return {
+            inital: false,
+            current: 0,
+            pageTotal: 1,
+            loading: false,
+            ending: false,
+            lastScrollTop: 0,
+            scrollTimer: 0,
+        };
+    },
+    methods: {
+        hanldeLoadMore() {
+            // 结束后跳过
+            if (this.ending) {
+                return;
+            }
+            // 加载中跳过
+            if (this.loading) {
+                return;
+            }
+            // 开始加载
+            this.inital = true;
+            this.loading = true;
+            this.onLoadMore({
+                current: this.current,
+                next: this.current + 1,
+                // 加载成功
+                success: (options) => {
+                    // 没有数据
+                    if (!options.pageTotal || options.pageTotal <= 0) {
+                        this.ending = true;
+                    }
+                    // 有数据
+                    else {
+                        this.pageTotal = options.pageTotal;
+                        this.current = this.current + 1;
+                        // 已到最后一页
+                        if (this.current >= this.pageTotal) {
+                            this.ending = true;
+                        }
+                    }
+                    setTimeout(() => {
+                        this.loading = false;
+                    }, 100);
+                },
+                // 加载失败
+                fail: () => {
+                    this.loading = false;
+                },
+            });
+        },
+        onScroll(evt) {
+            // 往上
+            if (this.lastScrollTop >= evt.detail.scrollTop) {
+                this.lastScrollTop = evt.detail.scrollTop;
+                return;
+            }
+            // 往下
+            else {
+                const viewHeight = evt.target.offsetHeight;
+                const { scrollTop, scrollHeight } = evt.detail;
+                // 阀值 100 像素,向下滚动到最后 100 像素,识别为启动加载
+                if (viewHeight + scrollTop >= scrollHeight - 100) {
+                    clearTimeout(this.scrollTimer);
+                    this.scrollTimer = setTimeout(() => {
+                        this.hanldeLoadMore();
+                    }, 200);
+                }
+            }
+        },
+        initScroll() {
+            // 已初始化,跳过
+            if (this.inital) {
+                return;
+            }
+            this.hanldeLoadMore();
+        },
+    },
+    mounted() {
+        // 开启自动初始化
+        if (this.autoInit) {
+            this.hanldeLoadMore();
+        }
+    },
+};
+</script>
\ No newline at end of file
diff --git a/plugins/infiniteScroll/cInfiniteScroll.scss b/plugins/infiniteScroll/cInfiniteScroll.scss
new file mode 100644
index 0000000..81f7b9c
--- /dev/null
+++ b/plugins/infiniteScroll/cInfiniteScroll.scss
@@ -0,0 +1,19 @@
+/**
+ * CInfiniteScroll
+ * @author Tevin
+ */
+
+@import "../../common/sassMixin";
+
+.c-infinite-scroll {
+    .bottom {
+        height: 1.8rem;
+        text-align: center;
+        line-height: 1.5rem;
+        color: #666;
+        .empty {
+            line-height: 5rem;
+            color: #999;
+        }
+    }
+}
\ No newline at end of file
diff --git a/plugins/infiniteScroll/index.js b/plugins/infiniteScroll/index.js
new file mode 100644
index 0000000..5cac221
--- /dev/null
+++ b/plugins/infiniteScroll/index.js
@@ -0,0 +1,10 @@
+/**
+ * CInfiniteScroll
+ * @author Tevin
+ */
+
+import CInfiniteScroll from '@components/plugins/infiniteScroll/CInfiniteScroll.vue';
+
+export {
+    CInfiniteScroll,
+}
\ No newline at end of file

--
Gitblit v1.9.1