Notes
  • 速记
  • 前端面试
  • HTML / CSS
    • HTML
    • CSS
    • CSS Modules
      • CSS Modules
        • CSS Modules Usage
      • Stylus
      • Nunjucks
  • Javascript
    • 正则表达式
    • 代理(Proxy)和反射(Reflection)
    • 类型转换
    • 按位操作
    • 数据可视化
    • 数据采集
      • 无(全)埋点
      • 模块曝光事件
    • package
      • axios
    • Event Loop
    • React
      • React热身
      • VDOM和DOM-diff
    • Vue
    • Omi
    • MVVM
    • 百度小程序
    • AST抽象语法树
    • ServiceWorker
    • WebSocket
  • NodeJS
    • Assert 断言
    • chai.js 断言库
    • Node Global Obj And Var
    • CLI Writed By Nodejs
    • Framework
      • Hapi Js Framework
    • Electrode JS
      • Electrode Platform
      • Electrode Question
    • Redux
      • Redux Basic Usage
      • Middleware And Asynchronous
      • React-Redux 的用法
    • NPM
      • package.json
      • semver
    • Webpack
      • 编写插件
    • 同构渲染
    • 调用DLL
  • 服务端
    • Inotify
    • Linux
    • Nginx
      • Nginx简介
      • Nginx原理、安装预配置
    • TCP/IP 协议
    • HTTP 协议
      • 基础概念篇
      • 协议详解篇
    • Process
      • 阻塞与非阻塞
      • 进程与线程优性能
  • 数据库
    • GraphQL
  • 移动端
  • 微信小程序
    • 微信小程序安装(linux)
    • 小程序第三方框架
  • 开发工具
    • 开发工具安装
    • Vim Command Collection
    • Git
      • Git Rule
      • Git Submodule
      • gitignore
    • Lerna
    • Ubuntu开发环境安装
  • 运维测试
    • Docker
      • Docker Synopsis
      • docker.sock
    • Nightwatch
    • Jest
  • 算法/数学/架构
    • 设计模式
    • 架构设计经验分享
    • 前端架构
    • 基本数据结构
    • 函数式编程
  • 软件工程
    • 软件生命周期
Powered by GitBook
On this page
  • IntersectionObserver API
  • API
  • callback 参数
  • IntersectionObserverEntry 对象
  • Option 对象
  • 代码示例

Was this helpful?

  1. Javascript
  2. 数据采集

模块曝光事件

Previous无(全)埋点Nextpackage

Last updated 5 years ago

Was this helpful?

IntersectionObserver API

传统的实现方法是: 监听到scroll事件后,调用目标元素(绿色方块)的getBoundingClientRect()方法,得到它对应于视口左上角的坐标,再判断是否在视口之内。这种方法的缺点是,由于scroll事件密集发生,计算量很大,容易造成性能问题。 交叉观察器

API

// 开始观察
io.observe(document.getElementById('example'));

// 停止观察
io.unobserve(element);

// 关闭观察器
io.disconnect();

callback 参数

callback一般会触发两次。一次是目标元素刚刚进入视口(开始可见),另一次是完全离开视口(开始不可见)

IntersectionObserverEntry 对象

{
  time: 3893.92,
  rootBounds: ClientRect {
    bottom: 920,
    height: 1024,
    left: 0,
    right: 1024,
    top: 0,
    width: 920
  },
  boundingClientRect: ClientRect {
     // ...
  },
  intersectionRect: ClientRect {
    // ...
  },
  intersectionRatio: 0.54,
  target: element
}
  • time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒

  • target:被观察的目标元素,是一个 DOM 节点对象

  • rootBounds:根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null

  • boundingClientRect:目标元素的矩形区域的信息

  • intersectionRect:目标元素与视口(或根元素)的交叉区域的信息

  • intersectionRatio:目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0

Option 对象

  • threshold: 设置门槛,触发回调函数

new IntersectionObserver(
  entries => {/* ... */}, 
  {
    threshold: [0, 0.25, 0.5, 0.75, 1]
  }
);
  • root: 容器

  • rootMargin: 它使用CSS的定义方法,比如10px 20px 30px 40px,表示 top、right、bottom 和 left 四个方向的值,用来扩展或缩小rootBounds这个矩形的大小

代码示例

this.autoTrackExpose = function () {
    if (!_this.getEnableExpose()) {
        util.log('未开启元素曝光');
    }
    common.bindEvent(window, 'scroll,click,resize', common.throttling(handleExposeSignal, EXPOSE_THROTTLE_TIME));
    handleExposeSignal();

    function handleExposeSignal () {
        var exposeNode = document.querySelectorAll('['+ EXPOSE_ATTR_FLAG +']');
        var viewportRect = common.getViewport();
        console.log(11);

        exposeNode.forEach(function (node) {
            var preStatus = node.isExposed;

            // 更新 isExposed
            node.isExposed = common.intersectRect(node.getBoundingClientRect(), viewportRect);
            node.nodeInfo = common.getTargetInfo(node);
            // 节点 destroy时需要 取消曝光心跳
            preStatus ? node.isExposed ? null :  exitExposeStatus(node) : node.isExposed ? inExposeStatus(node) : null;
        });

        function updateNodeHbTime (node) {
            node.mHbTime = new Date().getTime();
        }

        function inExposeStatus (node) {
            // 发送曝光事件
            _this.trackExpose(node.nodeInfo);
            updateNodeHbTime(node);
            // 曝光心跳
            var exposeHbObj = util.merge(node.nodeInfo);
            exposeHbObj.expTime = EXPOSE_HB_TIME;
            node.mTimeId = setInterval(function () {
                _this.trackExposeHb(exposeHbObj);
                // 更新 节点曝光时间
                updateNodeHbTime(node);
            }, EXPOSE_HB_TIME * 1000);
        }

        function exitExposeStatus (node) {
            var exposeHbObj = util.merge(node.nodeInfo);
            exposeHbObj.expTime = Math.ceil((new Date().getTime() - node.mHbTime) / 1000);
            clearInterval(node.mTimeId);
            _this.trackExposeHb(exposeHbObj);
        }
    }
};
模块曝光事件
IntersectionObserver API
API
callback 参数
IntersectionObserverEntry 对象
Option 对象
代码示例