前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React魔法堂:size-sensor源码略读

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

作者头像
^_^肥仔John
发布2022-10-31 11:49:59
4930
发布2022-10-31 11:49:59
举报

前言

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

源码介绍

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

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

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

用于监听Element内容盒子或边框盒子或者SVGElement边界尺寸的大小,并调用回调函数。

MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver

代码语言:javascript
复制
/**
 * @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事件实现对容器的尺寸的监听。

代码语言:javascript
复制
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/resize-observer-polyfill

Repos: https://github.com/juggle/resize-observer

尊重原创,转载请注明来自:https://cloud.tencent.com/developer/article/2145256 肥仔John

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 源码介绍
    • 基于浏览器原生API - ResizeObserver实现
      • 基于object元素的兼容方案实现
      • ResizeObserver的polyfill兼容方案 - MutationObserver
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档