先看效果:
众所周知,我们平时获取获取窗口的宽高都是 JavaScript
获取的,要不然直接通过 JavaScript
的 resize
监听页面宽高变化。
但现在不一样了!我们可以直接通过 CSS
获取 window
的尺寸,并且可以通过变量来进行使用。
在我第一眼看到这个消息的感觉是不可置信!但这是真的,下面我将带大家复习一下在 Vue、React、Svelte 以及原生 JavaScript
中如何获取 window
尺寸,然后带大家一览新的获取方案!
示例
点击马上掘金中间的左右箭头,可以查看高度的监听。
本来是先写的传统方案获取尺寸,但想到大家可能都了解怎么实现,就放在了后面,大家有需要可以自己在后面复习一下。😊😊
CSS 获取窗口大小
属性定义
通过 CSS 新增的 @property
,可以让我们创建自定义属性,并给它定义其类型以及初始值(初始值在不经改变的情况下一直是该值)。
利用这个功能,我们可以创建一个宽高属性出来。
1@property --w_raw {
2 syntax: '<length>';
3 inherits: true;
4 initial-value: 100vw;
5}
6
7@property --h_raw {
8 syntax: '<length>';
9 inherits: true;
10 initial-value: 100vh;
11}
这其中:
syntax
是这个属性的单位,我们给它设置为<length>
,以便于让浏览器理解这是一个长度单位initial-value
是这个属性的初始值,如果不修改,它一直是100vw
inherits
是这个属性是否可以被继承,设置false | true
都不影响使用
计算为数字
现在我们有一个 CSS 能识别的 length
,但这个单位我们不认识,所以我们要通过 CSS 提供的数学函数计算出真正的数字长度,因此我们要使用 CSS 数学工具中的 atans2(y, x)
和 tan()
。
atans(y, x)
:返回点 (x, y) 到原点的角度(弧度单位)tan()
:返回给定角度的正切
通过上面这两个数学函数,计算 --w_raw
与 --h-raw
到 1px
之间角度的正切值,进而得到宽高的纯数字。
将数字展示到页面
通过 CSS 的计数器将数字展示到页面上。
这其中:
counter(w)
:表示计数器 w 的值counter-reset: w var(--w)
:表示计数器 w 被重置为 —w 的值
1body::before {
2 content: counter(w) 'x' counter(h);
3 counter-reset: h var(--h) w var(--w);
4}
完整代码
1@property --w_raw {
2 syntax: '<length>';
3 inherits: false;
4 initial-value: 100vw;
5}
6
7@property --h_raw {
8 syntax: '<length>';
9 inherits: false;
10 initial-value: 100vh;
11}
12
13:root {
14 --w: tan(atan2(var(--w_raw), 1px));
15 --h: tan(atan2(var(--h_raw), 1px));
16}
17
18body::before {
19 position: fixed;
20 top: 50%;
21 left: 50%;
22 transform: translate(-50%, -50%);
23 content: counter(w) 'x' counter(h);
24 counter-reset: h var(--h) w var(--w);
25}
复习一下传统开发中的获取方案
JavaScript
在原生 JavaScript 中,我们通过 innerWidth
获取窗口宽度,然后通过监听 resize
变化重新赋值。
1let windowWidth = window.innerWidth;
2
3function handleResize = () => windowWidth = window.innerWidth
4
5window.addEventListener('resize', handleResize)
6window.addEventListener('resize', handleResize)
Vue
在 Vue3 中,我们可以通过自定义 Hook
的方式实现 resize
。
1import { ref, onMounted, onUnmounted } from 'vue';
2
3export function useWindowWidth() {
4 const windowWidth = ref(window.innerWidth);
5
6 const handleResize = () => {
7 windowWidth.value = window.innerWidth;
8 };
9
10 onMounted(() => {
11 window.addEventListener('resize', handleResize);
12 });
13
14 onUnmounted(() => {
15 window.removeEventListener('resize', handleResize);
16 });
17
18 return windowWidth;
19}
由于 Vue2 不支持自定义 Hook
,我们则需通过 Mixin
的方式实现。
1export const windowMixin = {
2 data() {
3 return {
4 windowWidth: window.innerWidth
5 };
6 },
7 methods: {
8 handleResize() {
9 this.windowWidth = window.innerWidth;
10 }
11 },
12 mounted() {
13 window.addEventListener('resize', this.handleResize);
14 },
15 beforeDestroy() {
16 window.removeEventListener('resize', this.handleResize);
17 }
18};
React
React 也是一个简单的 Hook
。
1import { useState, useEffect } from 'react';
2
3export function useWindowWidth() {
4 const [windowWidth, setWindowWidth] = useState(window.innerWidth);
5
6 useEffect(() => {
7 const handleResize = () => {
8 setWindowWidth(window.innerWidth);
9 };
10
11
12 handleResize();
13
14
15 window.addEventListener('resize', handleResize);
16
17
18 return () => {
19 window.removeEventListener('resize', handleResize);
20 };
21 }, []);
22
23 return windowWidth;
24}
通过上面文章,相信大家可以学会 CSS 如何实现监听 window 宽度,并且可以举一反三的利用该原理做更多的事情。✌️
同时我们还复习了多种语言中如何监听 window 宽度。