当您想到媒体查询时,想到的第一件事是什么?也许 CSS 文件中的内容如下所示:
body {
background-color: red;
}
@media (min-width: 768px) {
body {
background-color: blue;
}
}
CSS 媒体查询是我们在做响应式设计的核心要素。可以让我们根据设备显示器的特性(如视口宽度、屏幕比例、设备方向:横向或纵向)为其设定CSS样式,解决不同设备显示器 UI 适配问题,为不同设备类型的用户提供了最佳的视觉体验。
但是您知道 JavaScript 也有媒体查询的 API 吗?尽管我们用的少,但是真有,在 Javascript 中使用媒体查询对创建响应式元素非常方便,例如,在某个分辨率下,我们可能需要重新绘制并重新计算响应式元素大小。
matchMedia()
浏览器支持情况:
用法几乎与CSS媒体查询相同。我们将媒体查询字符串传递给matchMedia()。
const mediaQuery = window.matchMedia('(min-width: 768px)')
定义的媒体查询将返回一个MediaQueryList对象。该对象存储有关媒体查询的信息,而我们可以通过返回对象的matches属性来判断是否匹配。
const mediaQuery = window.matchMedia('(min-width: 768px)')
if (mediaQuery.matches) {
console.log('matchMedia')
}
addListener()
MediaQueryList 内置有 addListener() 和 removeListener() 方法,这两个方法是媒体查询状态更改时回调函数。当判断条件匹配时,我们可以触发自定义事件,从而使我们能够及时响应。
const mediaQuery = window.matchMedia('(min-width: 768px)')
function handleTabletChange(e) {
if (e.matches) {
console.log('Media Query Matched!')
}
}
mediaQuery.addListener(handleTabletChange)
handleTabletChange(mediaQuery)
注:第一次加载时,addListener() 默认不会调用。如果我们需要启动时调用,需要手动调用事件处理程序函数,并将媒体查询作为参数传递调用。
handleTabletChange(mediaQuery)
和 resize 的区别
以前监听窗口,我们最常用的做法是使用 resize,通过绑定 resize 事件监听检查window.innerWidth 或 window.innerHeight 。
function checkMediaQuery() {
if (window.innerWidth > 768) {
console.log('resize')
}
}
window.addEventListener('resize', checkMediaQuery);
由于每次浏览器调整大小都会调用 resize 事件,因此这是一项非常耗性能的做法!通过对比我们可以看到差异。调用 resize 缩放窗口共执行了 57 次,而通过 matchMedia 值执行了一次。
function checkMediaQuery() {
if (window.innerWidth > 768) {
console.log('resize!')
}
}
window.addEventListener('resize', checkMediaQuery);
const mediaQuery = window.matchMedia('(max-width: 768px)')
function handleTabletChange(e) {
if (e.matches) {
console.log('matchMedia!')
}
}
mediaQuery.addListener(handleTabletChange)
handleTabletChange(mediaQuery);
[图片上传失败...(image-1daf08-1611277684879)]
其次,通过 resize 只能通过window.innerWidth 或 window.innerHeight监听屏幕变化,而使用 matchMedia() 你可以传入 css 媒体查询的判断属性,如 设备宽高比(device-aspect-ratio)、宽高比(aspect-ratio)、方向(orientation)等,在用法上更加灵活。
const mediaQuery = window.matchMedia('(min-aspect-ratio: 1/1)')
const mediaQuery = window.matchMedia('(orientation: portrait)')