朋友们,美好的一天!响应式是Web开发的标准之一。屏幕分辨率很多,并且这个数字一直在增加。我们努力支持所有可能的屏幕尺寸,同时保持友好的用户界面。媒体查询(媒体查询)是解决此问题的绝佳方法。但是网络组件呢?现代Web开发基于组件,我们需要一种使它们响应的方法。今天,我想谈谈ResizeObserver API,它允许您监视(观察)特定元素(而不是整个视口)的大小变化,而不是像媒体查询那样监视整个视口。一点历史
以前,我们只有媒体查询可供使用-一种CSS解决方案,基于媒体设备的屏幕大小,类型和分辨率(媒体设备指的是计算机,电话或平板电脑)。媒体查询非常灵活且易于使用。长期以来,媒体查询仅在CSS中可用,现在它们也通过window.matchMedia(mediaQueryString)在JS中可用。现在,我们可以检查从哪个设备查看了该页面,还可以监视查看区域大小的变化(我们正在谈论MediaQueryList.addListener()方法-大约。元素查询
我们缺少的功能是监视单个DOM元素的大小,而不仅仅是整个视口的大小。多年来,开发人员一直对此抱怨。这是最令人期待的功能之一。在2015年,甚至提出了一个提案-集装箱尺寸要求(集装箱查询):开发人员在调整其父容器大小时通常需要具有样式元素的能力,而无论其查看区域是什么。集装箱尺寸的要求给了他们这个机会。CSS用法示例:
.element:媒体(最小宽度:30em)屏幕{***}
听起来不错,但浏览器供应商有充分的理由拒绝该建议-循环依赖(循环依赖)(当一种尺寸定义另一种尺寸时,这会导致无限循环(有关更多信息,请参见此处))。还有什么其他选择?我们可以使用window.resize(回调),但这是“昂贵的乐趣”-每当事件发生时都会调用回调,并且我们将需要进行大量计算才能确定组件的大小确实发生了变化。使用ResizeObserver API调整监视元素的大小
符合Chrome 的ResizeObserver API:ResizeObserver API是用于跟踪元素大小调整的接口。这是元素的window.resize事件的一种类似形式。
ResizeObserver API是实时草案。它已经在PC的Chrome,Firefox和Safari中实现。移动支持并不那么令人印象深刻-仅支持Android和Chrome浏览器和Chrome浏览器。不幸的是,不存在成熟的多聚体。可用的多聚体包含一些限制(例如,对调整大小的响应较慢或缺少对平滑过渡的支持)。但是,这不应阻止我们测试此API。让我们开始吧!示例:在调整元素大小时更改文本
想象一下以下情况-元素内的文本应根据元素的大小而变化。ResizeObserver API提供了两个工具-ResizeObserver和ResizeObserverEntry。ResizeObserver用于跟踪项目的大小,而ResizeObserverEntry包含有关已调整大小的项目的信息。代码很简单:<h1> size </h1>
<h2> boring text </h2>
const ro = new ResizeObserver(entries => {
for(let entry of entries){
const width = entry.contentBoxSize
? entry.contentBoxSize.inlineSize
: entry.contentRect.width
if(entry.target.tagName === 'H1'){
entry.target.textContent = width < 1000 'small' : 'big'
}
if(entry.target.tagName === 'H2' && width < 500){
entry.target.textContent = `I won't change anymore`
ro.unobserve(entry.target)
}
}
})
ro.observe(document.querySelector('h1'))
ro.observe(document.querySelector('h2'))
首先,创建一个ResizeObserver对象,并将回调函数作为参数传递给它:const resizeObserver = new ResizeObserver((entries, observer) => {
for(let entry of entries){
}
})
每次调整ResizeObserverEntries中包含的元素之一的大小时,都会调用该函数。回调函数的第二个参数是观察者本身。我们可以使用它来例如在满足特定条件时停止跟踪。回调获取ResizeObserverEntry数组。每个条目均包含观察元素(目标)的尺寸。for(let entry of entries){
const width = entry.contentBoxSize
? entry.contentBoxSize.inlineSize
: entry.contentRect.width
if(entry.target.tagName === 'H1'){
entry.target.textContent = width < 1000 ? 'small' : 'big'
}
...
}
我们具有三个描述元素大小的属性-borderBoxSize,contentBoxSize和contentRect。它们代表元素的盒模型,我们将在后面讨论。现在谈谈支持。大多数浏览器都支持contentRect,但是显然,此属性将被弃用:contentRect出现在ResizeObserver的初步开发阶段,仅出于当前兼容性的考虑而添加。将来可能会认为它已过时。
因此,我强烈建议将contentRect与bordeBoxSize和contentBoxSize结合使用。ResizeObserverSize包括两个属性:inlineSize和blockSize,它们可以解释为宽度和高度(前提是我们在文本的水平方向上工作-书写模式:水平)。元素观察
最后要做的是开始跟踪该项目。为此,我们调用ResizeObserver.observe()。此方法将新目标添加到观察项目列表。我们可以一次将一个或几个元素添加到此列表中:
ro.observe(document.querySelector('h1'))
ro.observe(document.querySelector('h2'))
第二个参数是“可选”。迄今为止,唯一可用的选项是box,它定义了块模型。可能的值是content-box(默认),border-box和device-pixel-content-box(仅Chrome)。在一台ResizeObserver中只能定义一个块模型。要停止监视,请使用ResizeObserver.unobserve(目标)。要停止跟踪所有元素,请使用ResizeObserver.disconnect()。块模型
内容框是块的内容,不带填充,边框和边距。边框包括填充和边框(无边距)。
设备像素内容框是元素的内容,以物理像素为单位。我没有看到使用此模型的示例,但似乎在使用画布时可能会派上用场。这是在Github上有关此主题的有趣讨论。观察者什么时候能发现变化?
每次调整目标元素的大小时都会调用一个回调。规格说明如下:- 从DOM中添加/删除被观察项时,将触发观察。
- 当被观察元素的显示属性设置为none时,将触发观察。
- 观察不适用于“未取代”的线元素。
- 观察不适用于CSS转换。
- , , .. , 0,0.
根据第一段,我们可以确定更改其子级时父容器中的更改。ResizeObserver API的这种用法的一个很好的例子是在添加新消息时向下滚动聊天窗口。一个例子可以在这里看到。还记得我之前提到的容器大小查询吗?关于他的循环依赖问题?因此,ResizeObserver API具有内置的解决方案,可以防止“调整大小”的无限循环。在这里阅读。感谢您的关注。有用的链接:MDN CanIUse规范开发团队的第一篇文章最受欢迎的polyfil