vueschool.io         @vueschoo_io

Rolf Haug

Teacher + co-founder @ Vue School

Meetup organizer in Oslo

Full Stack developer & Consultant

Foodie 🌶

Oslo, Norway

Alex

Kyriakidis

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

Consultant @ Building Link

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

Alexander Lichter

Lydia Hallie

Filip Rakowski

Application Shortcuts

with a Renderless Event Component

@rahaug

Global Events

window.addEventListener()
<button @click="doSomething">My Button</button>

@rahaug

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: {
    //...
  }
}

@rahaug

Component API

<event-listener event="scroll" @fired="doSomething" />

@rahaug

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" />

@rahaug

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" />

@rahaug

<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

@rahaug

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)
  }
}

@rahaug

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)
  }
}

@rahaug

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)
  }
}

@rahaug

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)
      })
  }
}

@rahaug

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

@rahaug

New Component API

<event-listener @keydown.space="toggleVideo"/>

Vue takes care of the .space key modifier for us automatically

🥳

@rahaug

Search Demo

@rahaug

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>

@rahaug

Table Demo

@rahaug

  • Download repo to play with examples
     
  • Resources available in the repo
     
  • vue-global-events by Damian and Eduardo

📸

vueschool.io         @vueschoo_io

@rahaug

Vue.js 3 courses
coming soon

🕺

vueschool.io/love/vueconfus

Grab your 1 month free-pass

📸

Booth

Ciao

👋

@rahaug

👋

vueschool.io

Application Shortcuts (Express)

By Rolf Haug

Application Shortcuts (Express)

Application Shortcuts with a Renderless Event Component (Express)

  • 570