vue-pseudo-window

πŸ–Ό Declaratively interface window/document/body in your Vue template

Usage no npm install needed!

<script type="module">
  import vuePseudoWindow from 'https://cdn.skypack.dev/vue-pseudo-window';
</script>

README

πŸ–Ό Pseudo Window

Vue component to bind event-handlers or classes to window/document/body!

Insert pseudo-window anywhere in your template:

<pseudo-window @resize.passive="handleResize" />

πŸ‘‰ Try out a demo in this CodePen!

πŸš€ Install

npm i vue-pseudo-window

πŸ™‹β€β™‚οΈ Why?

  • ✨ Cleaner code No longer pollute your component with .addEventListener() & .removeEventListener()
  • ♻️ Template API Use Vue's @event syntax to bind listeners to the window as like you would to any other element
  • πŸ’ͺ Robust Supports all event modifiers capture, passive, and once. SSR friendly.
  • πŸ₯ Tiny 819 B Gzipped!

Before

<template>
  ...
</template>

<script>
export default {

    // Your component would be polluted with event binding logic
    mounted() {
        window.addEventListener('resize', this.handleResize, { passive: true })
    },

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

    methods: {
        handleResize() {
            ...
        }
    }
}
</script>

After ✨

<template>
    <div>
        ...

        <!-- Insert pseudo-window anywhere in your template -->
        <pseudo-window @resize.passive="handleResize" />
    </div>
</template>

<script>
export default {

    // Much cleaner!
    methods: {
        handleResize() {
            ...
        }
    }
}
</script>

πŸ‘¨β€πŸ« Demos JSFiddle Demo

Adding listeners to window
<template>
    <div>
        <div>
            Window width: {{ winWidth }}
        </div>

        <pseudo-window
            <!-- Handle window resize with "passive" option -->
            @resize.passive="onResize"
        />
    </div>
</template>

<script>
import PseudoWindow from 'vue-pseudo-window';

export default {
    components: {
        PseudoWindow
    },
    
    data() {
        return {
            winWidth: 0
        }
    },

    methods: {
        onResize() {
            this.winWidth = window.innerWidth;
        }
    }
}
</script>
Adding class & listeners to document <html>
<template>
    <div>
        <pseudo-window
            document

            <!-- Add a class to <html> -->
            :class="$style.lockScroll"

            <!-- Handle document click -->
            @click="onClick"
        />
    </div>
</template>

<script>
import PseudoWindow from 'vue-pseudo-window';

export default {
    components: {
        PseudoWindow
    },

    methods: {
        onClick() {
            console.log('Document click!')
        }
    }
}
</script>

<style module>
.lockScroll {
    overflow: hidden;
}
</style>
Adding class & listeners to body <body>
<template>
    <div>
        <pseudo-window
            body

            <!-- Add a class to <body> -->
            :class="$style.lockScroll"

            <!-- Handle body click -->
            @click="onClick"
        />
    </div>
</template>

<script>
import PseudoWindow from 'vue-pseudo-window';

export default {
    components: {
        PseudoWindow
    },

    methods: {
        onClick() {
            console.log('Body click!')
        }
    }
}
</script>

<style module>
.lockScroll {
    overflow: hidden;
}
</style>
Only want one root element?

PseudoWindow is a functional component that returns exactly what's passed into it. By using it as the root component, its contents will pass-through.

<template>
    <pseudo-window
        @blur="pause"
        @focus="resume"
    >
        <video>
            <source
                src="/media/examples/flower.webm"
                type="video/webm"
            >
        </video>
    </div>
</template>

<script>
import PseudoWindow from 'vue-pseudo-window';

export default {
    components: {
        PseudoWindow
    },

    methods: {
        resume() {
            this.$el.play()
        },
        pause() {
            this.$el.pause()
        }
    }
}
</script>

πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ Related

  • vue-subslot - πŸ’ Pick 'n choose what you want from a slot passed into your Vue component
  • vue-proxi - πŸ’  Tiny proxy component for Vue.js
  • vue-vnode-syringe - 🧬Mutate your vNodes with vNode Syringe πŸ’‰