Create Project
$ vue create reaction-timer
Open Project in VSC
Start Server
$ npm run serve
Create Component Files
Block.vue Results.vue
Initialize Component Files
Type vue in editor and select <vue> with default vue.
Create App.vue
<template> <h1>Ninja Reaction Timer</h1> <button @click="start" v-bind:disabled="isPlaying">play</button> <Block v-if="isPlaying" :delay="delay" @end="endGame"></Block> <Results v-if="displayResults" :score="score"></Results> </template> <script> import Block from './components/Block.vue' import Results from './components/Results.vue' export default { name: 'App', data() { return { isPlaying: false, delay: null, score: null, displayResults: false } }, components: { Block, Results }, methods: { start() { this.delay = 2000 + Math.random() * 5000 this.isPlaying = true this.displayResults = false; }, endGame(reactionTime) { this.score = reactionTime this.isPlaying = false this.displayResults = true } } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #444; margin-top: 60px; } </style>
Create Block.vue
<template> <div v-if="showBlock" class="block" @click="stopTimer"> click me </div> </template> <script> export default { props: ['delay'], data() { return { showBlock: false, timer: null, reactionTime: 0 } }, mounted() { setTimeout(() => { this.showBlock = true this.startTimer() }, this.delay) }, methods: { startTimer() { this.timer = setInterval(() => { this.reactionTime += 10; }, 10) }, stopTimer() { clearInterval(this.timer) console.log(this.reactionTime) this.$emit('end', this.reactionTime) } } } </script> <style> .block { width: 400px; border-radius: 20px; background: #0faf87; color: white; text-align: center; padding: 100px 0; margin: 40px auto; } </style>
Create Results.vue
<template> <p>Reaction Time: {{ score }} milliseconds</p> <p>Rank: {{ rank }} </p> </template> <script> export default { props: ['score'], data() { return { rank: null } }, mounted() { if (this.score< 250) { this.rank = 'Ninja fingers' } else if (this.score < 400) { this.rank = 'Rapid reflexes' } else { this.rank = 'Snail pace' } } } </script> <style> </style>
Summary of Techniques
- Use v-if to conditionally display child components in main app component.
- Define props in child component to allow parent component to pass in data (via component attributes) to child component.
- Use hooks in child component to perform tasks at certain point (e.g. mounted) in the component life-cycle.
- Pass data from the child component back to the parent component via custom event when calling this.$emit(‘event-name’, data).
- Receive data from child component by registering handler on child component for custom-event emitted by the child component. Received data is automatically passed as argument to the handler (e.g. handler(data) {…})
© 2022, Eric.