React魔法堂:size-sensor源码略读

前言

echarts-for-react在对echarts进行轻量级封装的基础上,额外提供图表尺寸自适应容器尺寸的这小而实用的功能,而这功能的背后就是本文想介绍的size-sensor了。

源码介绍

size-sensor源码十分精简,主要是对原生APIResizeObserver方案和object元素方案进行检测和API统一化而已。

代码首先会检测当前运行时是否支持原生APIResizeObserver,若不支持则使用object元素方案。下面我们将对两种方案进行探讨。

基于浏览器原生API - ResizeObserver实现

用于监听Element内容盒子或边框盒子或者SVGElement边界尺寸的大小,并调用回调函数。
MDN: https://developer.mozilla.org...

/**
 * @param {ResizeObserverEntry} entries - 用于获取每个元素改变后的新尺寸
 * @param {ResizeObserver} observer
 * @see https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserverEntry
 */ 
function handleResize(entries, observer) {
  for (let entry of entries) {
    //......
  }
}
const target = document.getElementById('main')

const observer = new ResizeObserver(handleResize)

// 开始对指定DOM元素的监听
observer.observe(target)

// 结束对指定DOM元素的监听
observer.unobserve(target)

// 结束对所有DOM元素的监听
observer.disconnect()

注意:在handleResize中修改target的尺寸并不会导致递归调用handleResize函数。

基于object元素的兼容方案实现

object元素用于内嵌图像、音频、视频、Java applets、ActiveX、PDF和Flash等外部资源,因此其也会像iframe元素那样生成独立的browser context。
而browser context中Window实例的尺寸会保持和object元素的一致,因此可以通过订阅browser context中Window实例的resize事件实现对容器的尺寸的监听。

function bind(target, handle) {
  if (getComputedStyle(target).position === 'static') {
    target.style.position = 'relative'
  }

  let object = document.createElement('object')
  object.onload = () => {
    object.contentDocument.defaultView.addEventListener('resize', handle)
    // 初始化时先触发一次
    handle()
  }
  object.style.display = 'block'
  object.style.position = 'absolute'
  object.style.top = 0
  object.style.let = 0
  object.style.width = '100%'
  object.style.height = '100%'
  object.style.pointerEvents = 'none'
  object.style.zIndex = -1
  object.style.opacity = 0
  object.type = 'text/html'

  target.appendChild(object)
  object.data = 'about:data'

  return () => {
    if (object.contentDocument) {
      object.contentDocument.defaultView.removeEventListener('resize', handle)
    }
    if (object.parentNode) {
      object.parentNode.removeChild(object)
    }
  }
}

这里将object元素替换为iframe元素也是可以的,只需将object.data换成iframe.src即可。
注意:在handle中修改target的尺寸并会导致递归调用handle函数。

ResizeObserver的polyfill兼容方案 - MutationObserver

Repos: https://github.com/que-etc/re...
Repos: https://github.com/juggle/res...

尊重原创,转载请注明来自:https://www.cnblogs.com/fsjoh... 肥仔John


__肥子John
全栈工程师

《Petite-Vue源码剖析》作者

2.8k 声望
1.8k 粉丝
0 条评论
推荐阅读
从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木175阅读 14k评论 10

正则表达式实例
收集在业务中经常使用的正则表达式实例,方便以后进行查找,减少工作量。常用正则表达式实例1. 校验基本日期格式 {代码...} {代码...} 2. 校验密码强度密码的强度必须是包含大小写字母和数字的组合,不能使用特殊...

寒青56阅读 8.5k评论 11

JavaScript有用的代码片段和trick
平时工作过程中可以用到的实用代码集棉。判断对象否为空 {代码...} 浮点数取整 {代码...} 注意:前三种方法只适用于32个位整数,对于负数的处理上和Math.floor是不同的。 {代码...} 生成6位数字验证码 {代码...} ...

jenemy49阅读 7.2k评论 12

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木75阅读 7.2k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs42阅读 6.9k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木45阅读 8.7k评论 6

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木35阅读 6.7k评论 10

《Petite-Vue源码剖析》作者

2.8k 声望
1.8k 粉丝
宣传栏