Vue JS - 如何在窗口大小发生变化时获取窗口大小

sar*_*ara 12 html javascript vue.js

我是vuejs的新手,但每当我调整大小时我都试图获得窗口大小,这样我就可以将它与某个值进行比较,我需要根据屏幕大小来应用它.我也尝试使用watch属性,但不知道如何处理它,这可能是为什么它不起作用

  methods: {

    elem() {
     this.size = window.innerWidth;
     return this.size;
   },
  mounted() {
    if (this.elem < 767){ //some code }
   }
Run Code Online (Sandbox Code Playgroud)

Gor*_*ran 18

将此代码放在Vue组件中:

created() {
  window.addEventListener("resize", this.myEventHandler);
},
destroyed() {
  window.removeEventListener("resize", this.myEventHandler);
},
methods: {
  myEventHandler(e) {
    // your code for handling resize...
  }
}
Run Code Online (Sandbox Code Playgroud)

这将在事件上注册vue方法,为您提供完整的Vue对象以及事件对象,并在组件销毁(可用内存)上将其删除.

  • “文档”无效,但“窗口”有效。 (12认同)
  • 可以,但是我真的建议您取消此类事件。 (2认同)
  • 同样的答案还说“调整大小”是为窗口定义的,但不是为文档定义的 (2认同)
  • 此代码仅对单例组件有效,因为它将跨组件共享处理程序。如果您有多个组件,一旦第一个组件被破坏,它们就会停止工作。正确的方法是在视图模型(数据)内创建绑定函数。 (2认同)

小智 18

对于Vue3,您可以使用以下代码:

mounted() {
  window.addEventListener("resize", this.myEventHandler);
},
unmounted() {
  window.removeEventListener("resize", this.myEventHandler);
},
methods: {
  myEventHandler(e) {
    // your code for handling resize...
  }
}
Run Code Online (Sandbox Code Playgroud)

destroyed 和 beforeDestroyed 在 Vue3 中已被弃用,因此您可能需要使用 beforeUnmount 和 unmounted


Cal*_*twr 8

最简单的方法

https://www.npmjs.com/package/vue-window-size

预览

import Vue from 'vue';
import VueWindowSize from 'vue-window-size';

Vue.use(VueWindowSize);
Run Code Online (Sandbox Code Playgroud)

然后您可以像这样从您的组件正常访问它:

<template>
  <div>
    <p>window width: {{ windowWidth }}</p>
    <p>window height: {{ windowHeight }}</p>
  </div>
</template>
Run Code Online (Sandbox Code Playgroud)

  • 我不会称通过 NPM 安装新库是“最简单”的方法:)。特别是如果你[在没有构建工具的情况下使用 CDN 中的普通 Vue](https://vuejs.org/guide/quick-start.html#without-build-tools),它就无法工作。 (3认同)

agm*_*984 7

我查看了该库的代码vue-window-size,除了附加逻辑之外,它只是在窗口调整大小时添加了一个事件侦听器,并且看起来可以指示它去抖动。来源

对我来说最关键的问题是,当 vue-router 路由发生变化(使元素从 1000px 变为 4000px)时,我的 Vue SPA 应用程序不会发出窗口调整大小事件<html>,因此在观看由 p5 控制的画布元素时,这给我带来了各种问题.js 使用 .js 重新绘制壁纸p5.resizeCanvas()

我现在有一个不同的解决方案,涉及主动轮询页面的偏移高度。

首先要注意的是JavaScript内存管理,因此为了避免内存泄漏,我将setInterval放在created生命周期方法中,并将clearInterval放在beforeDestroy生命周期方法中:

created() {
    this.refreshScrollableArea = setInterval(() => {
        const { offsetWidth, offsetHeight } = document.getElementById('app');
        this.offsetWidth = offsetWidth;
        this.offsetHeight = offsetHeight;
    }, 100);
},

beforeDestroy() {
    return clearInterval(this.refreshScrollableArea);
},
Run Code Online (Sandbox Code Playgroud)

正如上面代码所暗示的,我还放置了一些初始状态:

data() {
    const { offsetWidth, offsetHeight } = document.querySelector('#app');

    return {
        offsetWidth,
        offsetHeight,
        refreshScrollableArea: undefined,
    };
},
Run Code Online (Sandbox Code Playgroud)

注意:如果您使用getElementById类似的东西this.id(即:作为此组件中的子元素的元素),document.getElementById(this.id)则将是未定义的,因为 DOM 元素从外到内加载,因此如果您看到源自data实例化的错误,请设置宽度/ 最初的高度0

然后,我放置一个观察者offsetHeight来监听高度变化并执行业务逻辑:

    watch: {
        offsetHeight() {
            console.log('offsetHeight changed', this.offsetHeight);

            this.state = IS_RESET;
            this.setState(this.sketch);
            return this.draw(this.sketch);
        },
    },
Run Code Online (Sandbox Code Playgroud)

结论:我用performance.now()和 进行了测试:

document.querySelector('#app').offsetHeight 
document.getElementById('app').offsetHeight
document.querySelector('#app').getClientBoundingRect().height
Run Code Online (Sandbox Code Playgroud)

所有的执行时间大约完全相同:0.2ms,因此上面的代码每 100 毫秒花费大约 0.2 毫秒。目前,我发现在我的应用程序中这是合理的,包括在我针对运行速度比我的本地计算机慢一个数量级的慢速客户端进行调整之后。

以下是自己研发的测试逻辑:

const t0 = performance.now();
const { offsetWidth, offsetHeight } = document.getElementById('app');
const t1 = performance.now();

console.log('execution time:', (t1 - t0), 'ms');
Run Code Online (Sandbox Code Playgroud)

奖励:如果由于函数执行时间较长而出现任何性能问题setInterval,请尝试将其包装在双 requestAnimationFrame 中:

created() {
    this.refreshScrollableArea = setInterval(() => {
        return requestAnimationFrame(() => requestAnimationFrame(() => {
            const { offsetWidth, offsetHeight } = document.getElementById(this.id);
            this.offsetWidth = offsetWidth;
            this.offsetHeight = offsetHeight;
        }));
    }, 100);
},
Run Code Online (Sandbox Code Playgroud)

requestAnimationFrame本身就是一个人应该研究的。我将把它排除在这个答案的范围之外。

最后,我后来研究但没有使用的另一个想法是使用setTimeout带有动态超时的递归函数(即:页面加载后衰减的超时);但是,如果您考虑递归 setTimeout 技术,请注意调用堆栈/函数队列长度和尾部调用优化。堆栈大小可能会超出您的预期。