v-infinite-scroll失效,v-infinite-scroll在弹窗中失效,在dialog中失效

v-infinite-scroll滚动到底或第一次都无法生效

1.弹窗启动时,未经过mounted生命周期,所以未绑定成功滚动事件

2.获得监听滚动函数的element时(getScrollEventTarget),也就是滚动的容器时,未能拿到overflowY的值,是根据这个值去返回当前滚动容器的元素。否则拿不到返回window的值。

解决办法也很简单粗暴,就是修改源码
下面附上源码(自定义指令)
const ctx = "@@InfiniteScroll";

const throttle = function (fn, delay) {
  let now, lastExec, timer, context, args; //eslint-disable-line

  const execute = function () {
    fn.apply(context, args);
    lastExec = now;
  };

  return function () {
    context = this;
    args = arguments;
    now = Date.now();

    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    if (lastExec) {
      const diff = delay - (now - lastExec);
      if (diff < 0) {
        execute();
      } else {
        timer = setTimeout(() => {
          execute();
        }, diff);
      }
    } else {
      execute();
    }
  };
};

const getScrollTop = function (element) {
  if (element === window) {
    return Math.max(window.pageYOffset || 0, document.documentElement.scrollTop);
  }

  return element.scrollTop;
};

const getComputedStyle = document.defaultView.getComputedStyle;

const getScrollEventTarget = function (element) {
  let currentNode = element;
  console.log("drawer:", element);
  // bugfix, see http://w3help.org/zh-cn/causes/SD9013 and http://stackoverflow.com/questions/17016740/onscroll-function-is-not-working-for-chrome
  while (currentNode && currentNode.tagName !== "HTML" && currentNode.tagName !== "BODY" && currentNode.nodeType === 1) {
    const overflowY = getComputedStyle(currentNode).overflowY;
    console.log("drawer:", overflowY);
    const overflowYStyle = currentNode.style.overflowY;
    console.log("drawer:", overflowYStyle);
    if (overflowY === "scroll" || overflowY === "auto" || overflowYStyle === "auto") {
      return currentNode;
    }
    console.log("drawer:", currentNode.parentNode);
    currentNode = currentNode.parentNode;
  }
  return currentNode;
};

const getVisibleHeight = function (element) {
  if (element === window) {
    return document.documentElement.clientHeight;
  }

  return element.clientHeight;
};

const getElementTop = function (element) {
  if (element === window) {
    return getScrollTop(window);
  }
  return element.getBoundingClientRect().top + getScrollTop(window);
};

const isAttached = function (element) {
  let currentNode = element.parentNode;
  while (currentNode) {
    if (currentNode.tagName === "HTML") {
      return true;
    }
    if (currentNode.nodeType === 11) {
      return false;
    }
    currentNode = currentNode.parentNode;
  }
  return false;
};

const doBind = function () {
  if (this.binded) return; // eslint-disable-line
  this.binded = true;

  const directive = this;
  const element = directive.el;
  console.log("directive:", directive, element.parentNode);
  const throttleDelayExpr = element.getAttribute("infinite-scroll-throttle-delay");
  let throttleDelay = 200;
  if (throttleDelayExpr) {
    throttleDelay = Number(directive.vm[throttleDelayExpr] || throttleDelayExpr);
    if (isNaN(throttleDelay) || throttleDelay < 0) {
      throttleDelay = 200;
    }
  }
  directive.throttleDelay = throttleDelay;

  directive.scrollEventTarget = getScrollEventTarget(element);
  directive.scrollListener = throttle(doCheck.bind(directive), directive.throttleDelay);
  directive.scrollEventTarget.addEventListener("scroll", directive.scrollListener);

  this.vm.$on("hook:beforeDestroy", function () {
    directive.scrollEventTarget.removeEventListener("scroll", directive.scrollListener);
  });

  const disabledExpr = element.getAttribute("infinite-scroll-disabled");
  let disabled = false;
  console.log("disabledExpr", disabledExpr);
  if (disabledExpr) {
    this.vm.$watch(disabledExpr, function (value) {
      directive.disabled = value;
      if (!value && directive.immediateCheck) {
        doCheck.call(directive);
      }
    });
    disabled = Boolean(directive.vm[disabledExpr]);
  }
  directive.disabled = disabled;

  const distanceExpr = element.getAttribute("infinite-scroll-distance");
  let distance = 0;
  if (distanceExpr) {
    distance = Number(directive.vm[distanceExpr] || distanceExpr);
    if (isNaN(distance)) {
      distance = 0;
    }
  }
  directive.distance = distance;

  const immediateCheckExpr = element.getAttribute("infinite-scroll-immediate-check");
  let immediateCheck = true;
  if (immediateCheckExpr) {
    immediateCheck = Boolean(directive.vm[immediateCheckExpr]);
  }
  directive.immediateCheck = immediateCheck;

  if (immediateCheck) {
    doCheck.call(directive);
  }

  const eventName = element.getAttribute("infinite-scroll-listen-for-event");
  if (eventName) {
    directive.vm.$on(eventName, function () {
      doCheck.call(directive);
    });
  }
};

const doCheck = function (force) {
  const scrollEventTarget = this.scrollEventTarget;
  const element = this.el;
  const distance = this.distance;

  if (force !== true && this.disabled) return; //eslint-disable-line
  const viewportScrollTop = getScrollTop(scrollEventTarget);
  const viewportBottom = viewportScrollTop + getVisibleHeight(scrollEventTarget);

  let shouldTrigger = false;

  if (scrollEventTarget === element) {
    shouldTrigger = scrollEventTarget.scrollHeight - viewportBottom <= distance;
  } else {
    const elementBottom = getElementTop(element) - getElementTop(scrollEventTarget) + element.offsetHeight + viewportScrollTop;

    shouldTrigger = viewportBottom + distance >= elementBottom;
  }

  if (shouldTrigger && this.expression) {
    this.expression();
  }
};

export default {
  // bind
  // bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  // inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
  inserted(el, binding, vnode) {
    el[ctx] = {
      el,
      vm: vnode.context,
      expression: binding.value,
    };
    const args = arguments;

    doBind.call(el[ctx]);
    el[ctx].vm.$nextTick().then(function () {
      if (isAttached(el)) {
        doBind.call(el[ctx], args);
      }

      el[ctx].bindTryCount = 0;

      const tryBind = function () {
        if (el[ctx].bindTryCount > 10) return; //eslint-disable-line
        el[ctx].bindTryCount++;
        if (isAttached(el)) {
          doBind.call(el[ctx], args);
        } else {
          setTimeout(tryBind, 50);
        }
      };
      tryBind();
    });
  },

  unbind(el) {
    if (el && el[ctx] && el[ctx].scrollEventTarget) {
      el[ctx].scrollEventTarget.removeEventListener("scroll", el[ctx].scrollListener);
    }
  },
};

使用方式
import infiniteScroll from './directive';
export default {
  directives: { infiniteScroll },
}//将上述代码的js放在文件夹下,直接引用,其实就是把vue-infinate-scroll包里的js抽出来,自己改了,按照原来的用法用就行了
然后按正常方式使用就行了
最后,有什么不懂的地方欢迎留言
我创建了一个技术交流微信群
加我V,拉你进群,备注来意
置顶的博客有二维码,可加我V
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值