How can I use window size in Vue? (How do I detect the soft keyboard?)

Solution 1:

I am sure there are better ways to do this, but this one will work for you until I come up with something:

Basically you will need just one data prop and one watcher to do this.

new Vue({
    el: '#app',
    data() {
        return {
            windowHeight: window.innerHeight,
            txt: ''
        }
    },

    watch: {
        windowHeight(newHeight, oldHeight) {
            this.txt = `it changed to ${newHeight} from ${oldHeight}`;
        }
    },

    mounted() {
        this.$nextTick(() => {
            window.addEventListener('resize', this.onResize);
        })
    },

    beforeDestroy() { 
        window.removeEventListener('resize', this.onResize); 
    },

    methods: {  
        onResize() {
            this.windowHeight = window.innerHeight
        }
    }
});

And this would output the changes

<div id="app">
    <br> Window height: {{ windowHeight }} <br/>
    {{ txt }}
</div>

Solution 2:

VUE 3

In Vue 3, you can create a function that can return a reactive width and breakpoint name values. You can easily reuse the function across multiple components.

import { computed, onMounted, onUnmounted, ref } from "vue"

export default function () {
  let windowWidth = ref(window.innerWidth)

  const onWidthChange = () => windowWidth.value = window.innerWidth
  onMounted(() => window.addEventListener('resize', onWidthChange))
  onUnmounted(() => window.removeEventListener('resize', onWidthChange))
  
  const type = computed(() => {
    if (windowWidth.value < 550) return 'xs'
    if (windowWidth.value >= 550 && windowWidth.value < 1200) return 'md'
    if (windowWidth.value >= 1200) return 'lg'
    return null; // This is an unreachable line, simply to keep eslint happy.
  })

  const width = computed(() => windowWidth.value)

  return { width, type }
}

You can use this in the setup method of your vue 3 component as follows.

const { width, type } = useBreakpoints()

Quick tip: Even though document event listeners are the most optimized things in the planet, this is best used only once in an app for performance reasons. Make a tiny plugin and add the value to the Vue instance, just like Vuetify does. Or to be simpler, commit them to vuex and read from there.