Skip to content

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

License

Notifications You must be signed in to change notification settings

privatenumber/vue-pseudo-window

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

99 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ–Ό 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 πŸ’‰