Pseudo Window
Declaratively interface window/document/body in your Vue template.
Insert pseudo-window anywhere in your template:
<pseudo-window @resize.passive="handleResize" />
? 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
, andonce
. 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
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>