Browse Source

feat: infinitelaoding

yangxiaolu3 3 years ago
parent
commit
26389128be

+ 17 - 8
src/packages/__VUE/infiniteloading/demo.vue

@@ -1,6 +1,15 @@
 <template>
   <div class="demo">
-    <nut-tabs v-model="tabsValue" animatedTime="0" @change="chagetabs">
+    <nut-infiniteloading
+      v-model="infinityValue2"
+      load-txt="Loading..."
+      :load-more-txt="translate('none')"
+      :has-more="customHasMore"
+      @load-more="customLoadMore"
+    >
+      <li class="infiniteLi" v-for="(item, index) in customList" :key="index">{{ item }}</li>
+    </nut-infiniteloading>
+    <!-- <nut-tabs v-model="tabsValue" animatedTime="0" @change="chagetabs">
       <nut-tabpane :title="translate('basic')">
         <ul class="infiniteUl" id="scroll">
           <nut-infiniteloading
@@ -21,8 +30,6 @@
             v-model="infinityValue2"
             load-txt="Loading..."
             :load-more-txt="translate('none')"
-            container-id="customScroll"
-            :use-window="false"
             :has-more="customHasMore"
             @load-more="customLoadMore"
           >
@@ -30,7 +37,7 @@
           </nut-infiniteloading>
         </ul>
       </nut-tabpane>
-    </nut-tabs>
+    </nut-tabs> -->
   </div>
 </template>
 
@@ -117,8 +124,10 @@ export default createDemo({
 
     const customLoadMore = () => {
       setTimeout(() => {
-        data.customList = data.defultList.concat(letter);
+        data.customList = data.customList.concat(letter);
         cycle2++;
+
+        console.log(cycle2, data.customList);
         if (cycle2 > 2) customHasMore.value = false;
 
         data.infinityValue2 = false;
@@ -153,6 +162,7 @@ export default createDemo({
 
 <style lang="scss" scoped>
 .demo {
+  overflow: inherit !important;
   padding-left: 0px !important;
   padding-right: 0px !important;
 }
@@ -167,12 +177,11 @@ export default createDemo({
   padding-left: 16px !important;
 }
 .infiniteUl {
-  height: calc(100vh - 110px);
   width: 100%;
   padding: 0;
   margin: 0;
-  overflow-y: auto;
-  overflow-x: hidden;
+  /* overflow-y: auto; */
+  /* overflow-x: hidden; */
 }
 .infiniteLi {
   font-size: 14px;

+ 12 - 21
src/packages/__VUE/infiniteloading/index.vue

@@ -36,7 +36,7 @@ import {
 } from 'vue';
 import { createComponent } from '@/packages/utils/create';
 const { componentName, create, translate } = createComponent('infiniteloading');
-import { useTouch } from '@/packages/utils/useTouch';
+import { useScrollParent } from '@/packages/utils/useScrollParent';
 import requestAniFrame from '@/packages/utils/raf';
 import { getScrollTopRoot } from '@/packages/utils/util';
 
@@ -82,10 +82,10 @@ export default create({
   emits: ['scroll-change', 'load-more', 'update:modelValue'],
 
   setup(props, { emit, slots }) {
-    const touch: any = useTouch();
+    const scroller = ref<HTMLElement>();
+    const scrollParent = useScrollParent(scroller);
     const state = reactive({
       scrollEl: window as Window | HTMLElement | (Node & ParentNode),
-      scroller: null as null | HTMLElement,
       beforeScrollTop: 0,
       isInfiniting: false,
       y: 0,
@@ -109,16 +109,17 @@ export default create({
       let resScrollTop = 0;
       let direction = 'down';
 
-      if (props.useWindow) {
+      if (scrollParent.value == window) {
         const windowScrollTop = getScrollTopRoot();
 
-        if (state.scroller) {
+        if (scroller.value) {
           offsetDistance =
-            calculateTopPosition(state.scroller) + state.scroller.offsetHeight - windowScrollTop - window.innerHeight;
+            calculateTopPosition(scroller.value) + scroller.value.offsetHeight - windowScrollTop - window.innerHeight;
         }
+
         resScrollTop = windowScrollTop;
       } else {
-        const { scrollHeight, clientHeight, scrollTop } = state.scrollEl as HTMLElement;
+        const { scrollHeight, clientHeight, scrollTop } = scrollParent.value as HTMLElement;
 
         offsetDistance = scrollHeight - clientHeight - scrollTop;
         resScrollTop = scrollTop;
@@ -143,7 +144,6 @@ export default create({
           return false;
         } else {
           state.isInfiniting = true;
-
           emit('update:modelValue', true);
           nextTick(() => emit('load-more'));
         }
@@ -151,22 +151,14 @@ export default create({
     };
 
     const scrollListener = () => {
-      state.scrollEl.addEventListener('scroll', handleScroll, props.useCapture);
-    };
-
-    // 滚动监听对象
-    const getParentElement = (el: HTMLElement) => {
-      return !!props.containerId ? document.querySelector(`#${props.containerId}`) : el && el.parentNode;
+      scrollParent.value && scrollParent.value.addEventListener('scroll', handleScroll, props.useCapture);
     };
 
     const removeScrollListener = () => {
-      state.scrollEl.removeEventListener('scroll', handleScroll, props.useCapture);
+      scrollParent.value && scrollParent.value.removeEventListener('scroll', handleScroll, props.useCapture);
     };
 
     onMounted(() => {
-      const parentElement = getParentElement(state.scroller as HTMLElement) as Node & ParentNode;
-      state.scrollEl = props.useWindow ? window : parentElement;
-
       scrollListener();
     });
 
@@ -191,9 +183,7 @@ export default create({
     watch(
       () => props.modelValue,
       (val) => {
-        console.log('监听', val);
-        if (val) {
-        } else {
+        if (!val) {
           state.isInfiniting = false;
         }
       }
@@ -201,6 +191,7 @@ export default create({
 
     return {
       classes,
+      scroller,
       ...toRefs(state),
       translate,
       slots

+ 37 - 0
src/packages/utils/useScrollParent/index.ts

@@ -0,0 +1,37 @@
+import { ref, Ref, onMounted } from 'vue';
+
+type ScrollElement = HTMLElement | Window;
+
+const overflowScrollReg = /scroll|auto|overlay/i;
+const defaultRoot = window;
+
+function isElement(node: Element) {
+  const ELEMENT_NODE_TYPE = 1;
+  return node.tagName !== 'HTML' && node.tagName !== 'BODY' && node.nodeType === ELEMENT_NODE_TYPE;
+}
+
+export function getScrollParent(el: Element, root: ScrollElement | undefined = defaultRoot) {
+  let node = el;
+
+  while (node && node !== root && isElement(node)) {
+    const { overflowY } = window.getComputedStyle(node);
+    if (overflowScrollReg.test(overflowY)) {
+      return node;
+    }
+    node = node.parentNode as Element;
+  }
+
+  return root;
+}
+
+export function useScrollParent(el: Ref<Element | undefined>, root: ScrollElement | undefined = defaultRoot) {
+  const scrollParent = ref<Element | Window>();
+
+  onMounted(() => {
+    if (el.value) {
+      scrollParent.value = getScrollParent(el.value, root);
+    }
+  });
+
+  return scrollParent;
+}