vueschool.io @vueschoo_io
Rolf Haug

Teacher @ Vue School
Vue.js Community Partner
Vue.js Oslo meetups organizer
Full Stack developer & Consultant
Foodie 🌶


Oslo, Norway

Alex
Kyriakidis

Teacher @ Vue School
Author of The Majesty of Vue.js 1 & 2
Vue.js Contributor
Enterprise Consultant


Amsterdam


#1 Learning Resource for Vue.js
Our goal
300+ Lessons from 20 video courses
70 000 users have joined us already!










Alex Kyriakidis
Rolf Haug
Debbie O'Brien
Chris Fritz
Maria Lamardo
Roman Kuba
Sébastien Chopin
Alexandre Chopin
Alexander Lichter
Lydia Hallie


💪 🤓
Power User

I love...
...shortcuts
You probably do too?
Why don't we implement more keyboard shortcuts in our web apps?
Application Shortcuts
with a Renderless Event Component
Global Events
window.addEventListener()
<button @click="doSomething">My Button</button>
What is a
Renderless Component?
<template>
...
</template>
<script>
export default {
props: {
//...
},
data () {
return { ... }
}
methods: {
// ...
}
}
</script>
Does not render it's own HTML
Only manages state and behavior
Render function
export default {
render () {
},
data () {
return {
// ...
}
},
methods: {
//...
}
}
Component API
<event-listener event="scroll" @fired="doSomething" />
EventListener.vue
export default {
render () {},
props: {
event: {
type: String,
required: true
}
},
methods: {
handle (e) {
this.$emit('fired', e)
}
},
mounted () {
window.addEventListener(this.event, this.handle)
},
destroyed () {
window.removeEventListener(this.event, this.handle)
}
}
Scroll Demo
<event-listener event="scroll" @fired="changeBackgroundColor" />
Network Demo
<event-listener event="offline" @fired="showOfflineMessage" />
<event-listener event="online" @fired="hideOfflineMessage" />
👆 Native events
Network Event
Notify the user or restrict certain actions
Shortcuts Demo
Play/Pause Demo
<event-listener event="keyup" @fired="toggleVideo"/>
// ...
methods: {
toggleVideo (event) {
if (event.code === 'Space') {
const video = this.$refs.video
video.paused ? video.play() : video.pause()
}
}
}
<video ref="video" src="/puppiness.mp4" />
<event-listener event="keyup" @fired="toggleVideo"/>
<event-listener @keydown.space="toggleVideo"/>
How can we use the v-on directive instead?
Doesn't feel like proper Vue
How can we get the listeners?
export default {
render () {},
props: {
event: {
type: String,
required: true
}
},
methods: {
handle (e) {
this.$emit('fired', e)
}
},
mounted () {
window.addEventListener(this.event, this.handle)
},
destroyed () {
window.removeEventListener(this.event, this.handle)
}
}
Register listeners
export default {
render () {},
props: {
event: {
type: String,
required: true
}
},
methods: {
handle (e) {
this.$emit('fired', e)
}
},
mounted () {
Object.keys(this.$listeners)
.forEach(event => {
const handler = this.$listeners[event]
window.addEventListener(event, handler)
})
},
destroyed () {
window.removeEventListener(this.event, this.handle)
}
}
Refactor
export default {
render () {},
props: {
event: {
type: String,
required: true
}
},
methods: {
handle (e) {
this.$emit('fired', e)
}
},
mounted () {
Object.keys(this.$listeners)
.forEach(event => {
const handler = this.$listeners[event]
window.addEventListener(event, handler)
})
},
destroyed () {
window.removeEventListener(this.event, this.handle)
}
}
Remove listeners
export default {
render () {},
mounted () {
Object.keys(this.$listeners)
.forEach(event => {
const handler = this.$listeners[event]
window.addEventListener(event, handler)
})
},
destroyed () {
Object.keys(this.$listeners)
.forEach(event => {
const handler = this.$listeners[event]
window.removeEventListener(event, handler)
})
}
}
export default {
render () {},
mounted () {
Object.keys(this.$listeners)
.forEach(event => {
const handler = this.$listeners[event]
window.addEventListener(event, handler)
})
},
destroyed () {
Object.keys(this.$listeners)
.forEach(event => {
const handler = this.$listeners[event]
window.removeEventListener(event, handler)
})
}
}
Event Listener 2.0
New Component API
<event-listener @keydown.space="toggleVideo"/>
Vue takes care of the .space key modifier for us automatically
🥳
Refactor handler
// ...
methods: {
toggleVideo (event) {
if (event.code === 'Space') {
const video = this.$refs.video
video.paused ? video.play() : video.pause()
}
}
}
Network Example
<event-listener event="offline" @fired="showOfflineMessage" />
<event-listener event="online" @fired="hideOfflineMessage" />
<event-listener @offline="showOfflineMessage" @online="hideOfflineMessage" />
Search Demo
cmd + f / ctrl + f
<event-listener
@keydown.meta.70="showSearch = true"
@keydown.ctrl.70="showSearch = true"
@keydown.esc="showSearch = false"
/>
<div v-if="showSearch">
<!-- awesome search form goes here -->
</div>
Table Demo
Companion Repository
with resources
📸
vue-global-events
github.com/shentao/vue-global-events


Damian Dulisz
Eduardo San Martin Morote
@DamianDulisz
@posva
vueschool.io @vueschoo_io
@rahaug
Vue.js 3 courses
coming soon
🕺
vueschool.io/love/vue-amsterdam

Grab your 1 month free-pass
Booth










Ciao
👋
Application Shortcuts (2020 Vue Amsterdam)
By Rolf Haug
Application Shortcuts (2020 Vue Amsterdam)
Application Shortcuts with a Renderless Event Component
- 637