[Vue] 如何利用intersectionOberver实现全局appear/disappear事件

期望的使用方式




那么就需要让如下操作生效

el.addEventListener('appear', callback)
el.addEventListener('disappear', callback)
el.removeEventListener('appear', callback)
el.removeEventListener('disappear', callback)

那么问题来, intersectionOberver是作为appear, disappear事件的触发者, 就需要Hook addEventListenerremoveEventListener做一些注册工作了.

extend(EventTarget.prototype, 'addEventListener', function(eventName) {
  let node = this;
  let ioContext = node.__IO__;

  if (eventName === 'appear' || eventName === 'disappear') {
    // 一个节点需要一个 io 即可
    if (node.__IO__) {
      ioContext.listenerNum++;
      return;
    }

    let io = new IntersectionObserver(entries => {
      const ioContext = node.__IO__;
      const { visible: lastVisible } = ioContext;
      const entry = entries[entries.length - 1];
      const ratio = entry.intersectionRatio;
      const visible = entry.isIntersecting && ratio >= 0;

      if (lastVisible === undefined) {
        ioContext.visible = visible;
      } else if (visible !== lastVisible) {
        ioContext.visible = visible;

        node.dispatchEvent(
          new CustomEvent(visible ? 'appear' : 'disappear', {
            bubbles: false // appear/disappear是节点相关的事件不能冒泡
          })
        );
      }
    });

    node.__IO__ = {
      instance: io,
      listenerNum: 1
    };
    io.observe(node);
  }
});

extend(EventTarget.prototype, 'removeEventListener', function(eventName) {
  let node = this;
  let ioContext = node.__IO__;

  if (eventName === 'appear' || eventName === 'disappear') {
    // 当事件为没有监听器的时候就可以把 io 注销, 释放内存
    if (--ioContext.listenerNum === 0) {
      ioContext.instance.disconnect();
      ioContext.instance = null;
      node.__IO__ = null;
    }
  }
});

function extend(obj, fnName, cb) {
  const oldFn = obj[fnName];
  obj[fnName] = function wrap() {
    let ret;
    oldFn && (ret = oldFn.apply(this, arguments));
    cb && cb.apply(this, arguments);
    return ret;
  };
}

实际效果如下:


[Vue] 如何利用intersectionOberver实现全局appear/disappear事件_第1张图片
appear,disappear.gif

CodePen Demo

你可能感兴趣的:([Vue] 如何利用intersectionOberver实现全局appear/disappear事件)