【问题标题】:Vue JS - How to get window size whenever it changesVue JS - 如何在窗口发生变化时获取窗口大小
【发布时间】:2018-08-29 01:37:21
【问题描述】:

我是 vuejs 的新手,但每当我尝试获取窗口大小时 调整它的大小,以便我可以将它与我的函数的某个值进行比较 需要根据屏幕大小来申请。我也尝试使用 watch 属性,但不知道如何处理它,所以这可能是它不起作用的原因

  methods: {

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

【问题讨论】:

标签: javascript html vue.js


【解决方案1】:

将此代码放入您的 Vue 组件中:

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

这将在创建组件时注册您的 Vue 方法,在调整浏览器窗口大小时触发 myEventHandler,并在您的组件被销毁时释放内存。

【讨论】:

  • 有效,但我真的建议对此类事件进行去抖动。
  • 您可以轻松地将 debounce 应用到任何 vue 方法。
  • 我知道,只是为 OP 做个笔记
  • 同样的答案还说'resize'是为窗口定义的,但不是为文档定义的
  • 此代码仅对单例组件有效,因为它将跨组件共享处理程序。如果您有多个组件,它们将在第一个被销毁后立即停止工作。正确的方法是在视图模型(数据)中创建一个绑定函数。
【解决方案2】:

最简单的方法

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

预览

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

Vue.use(VueWindowSize);

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

<template>
  <div>
    <p>window width: {{ windowWidth }}</p>
    <p>window height: {{ windowHeight }}</p>
  </div>
</template>

【讨论】:

    【解决方案3】:

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

    对我来说最关键的问题是,当 vue-router 路由发生变化时,我的 Vue SPA 应用程序不会发出窗口调整大小事件,这使得 &lt;html&gt; 元素从 1000 像素变为 4000 像素,所以这给我带来了各种观看问题由 p5.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);
    },
    

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

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

    注意:如果您将getElementByIdthis.id 之类的东西一起使用(即:该组件中的子元素),document.getElementById(this.id) 将未定义,因为 DOM 元素加载外部-to-inner,因此如果您看到由 data 实例化引起的错误,请先将宽度/高度设置为 0

    然后,我在offsetHeight 上设置了一个监听器来监听高度变化并执行业务逻辑:

        watch: {
            offsetHeight() {
                console.log('offsetHeight changed', this.offsetHeight);
    
                this.state = IS_RESET;
                this.setState(this.sketch);
                return this.draw(this.sketch);
            },
        },
    

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

    document.querySelector('#app').offsetHeight 
    document.getElementById('app').offsetHeight
    document.querySelector('#app').getClientBoundingRect().height
    

    所有执行的时间都差不多: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');
    

    奖励:如果您因setInterval 函数的长时间运行而遇到任何性能问题,请尝试将其包装在双请求动画框架中:

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

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

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

    【讨论】:

      【解决方案4】:

      你可以随时随地使用它

      methods: {
          //define below method first.
          winWidth: function () {
              setInterval(() => {
                  var w = window.innerWidth;
                  if (w < 768) {
                      this.clientsTestimonialsPages = 1
                  } else if (w < 960) {
                      this.clientsTestimonialsPages = 2
                  } else if (w < 1200) {
                      this.clientsTestimonialsPages = 3
                  } else {
                      this.clientsTestimonialsPages = 4
                  }
              }, 100);
          }
      },
      mounted() {
          //callback once mounted
          this.winWidth()
      }
      

      【讨论】:

      • 它确实有效,但实际上没有必要每秒运行 10 次该函数,因为事件侦听器只会根据需要触发,就像在接受的答案中一样。
      • 是的@hanenbro 我很久以前就发布了这个,现在我意识到这可以在没有 setInterval 的情况下运行,只需将我的方法回调为 Goran 的答案link
      猜你喜欢
      • 1970-01-01
      • 2015-07-21
      • 2011-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-15
      • 1970-01-01
      相关资源
      最近更新 更多