zoukankan      html  css  js  c++  java
  • vue——利用intersectionOberver实现全局appear/disappear事件

    搬运自:https://juejin.im/post/5cd10959f265da03a00fe5c6

    效果:

    demo地址: https://codepen.io/deepkolos/pen/OYPNNv?editors=1011

    vue:

    <template>
        <div @appear="onAppear" @disappear="onDisappear">box</div>
    </template>
    
    <script>
    export default {
        methods: {
            onAppear() { console.log('onAppear') },
            onDisappear() { console.log('onDisappear') }
        }
    }
    </script>

    js:

    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;
      };
    }
  • 相关阅读:
    例子:进度条制作
    例子:滑动效果
    例子:选项卡效果
    例子:图片轮播
    9.23 开课第二十天 (事件)
    例子:日期时间选择
    例子:两个列表之间移动数据
    php数据访问基础
    php面向对象加载类、常用设计模式
    php面向对象中的静态与抽象,接口
  • 原文地址:https://www.cnblogs.com/linjiangxian/p/11598316.html
Copyright © 2011-2022 走看看