Reputation: 1503
building a rock paper scissors game and want to make the computer choose a random hand. so far so good.
i want that the computer gets triggered with a event listener like v-on:humanChoosedHand="startGame()"
to choose a hand, WHEN the player/human has choosed a hand as well.
i can check and see the event humanChoosedHand
gets fired when i choose a hand for the human, but the parent GameField.vue
is not listening
code looks like this:
the parent GameField.vue
<template>
<div id="game-field">
<button class="btn btn-primary" @click="startGame()">Start</button>
<div class="row">
<div class="col-md-6 pt-5">
<Human></Human>
</div>
<div class="col-md-6 pt-5">
<Computer ref="computer" v-on:humanChoosedHand="startGame()"></Computer>
</div>
</div>
</div>
</template>
<script>
import Human from './Human.vue'
import Computer from './Computer.vue'
export default {
data: () => {
return {
score: [
{
human: 0
},
{
computer: 0
}
]
}
},
components: {
Human,
Computer
},
props: {
difficulty: String
},
methods: {
startGame () {
console.log('Game Started')
// this.$refs.computer.shuffleAnimation()
this.$refs.computer.setRandomHand() //<-----
// listen to emit here, not in html template
},
testFunction () {
console.log('test')
}
}
}
</script>
<style lang="scss">
#game-field {
.far {
cursor: pointer;
font-size: 300px;
width: 350px;
height: 350px;
}
.row {
margin: 0 0 0 0;
.select-hand {
position: relative;
left: 60px;
.far {
font-size: 80px;
height: 0;
width: 0;
}
.far:hover {
color: $orange;
}
}
}
.btn-primary {
background-color: $orange;
border-color: $orange;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, 30%);
}
.btn-primary:focus {
background-color: $orange;
border-color: $black !important;
box-shadow: 0 0 0 0.2rem rgba(255, 51, 0, 0.644);
}
}
</style>
then the child Computer.vue
:
<template>
<div id="computer">
<div class="text-center">
<div class="h2 mb-5">Computer</div>
<i class="far" :class="playIcon"></i>
<div class="hand h3 mt-4">{{ activeHand }}</div>
</div>
</div>
</template>
<script>
export default {
data: () => {
return {
winCounter: 0,
activeHand: 'I am ready',
playIcon: '',
hands: [
{
name: 'Rock',
strength: 'scissor',
weakness: 'paper',
icon: 'fa-hand-rock'
},
{
name: 'Paper',
strength: 'rock',
weakness: 'scissor',
icon: 'fa-hand-paper'
},
{
name: 'Scissor',
strength: 'paper',
weakness: 'rock',
icon: 'fa-hand-scissors'
}
]
};
},
methods: {
setRandomHand() {
// THIS SHOULD LISTEN TO THE 'humanChoosedHand'
// and should gets triggered by a 'ref.computer.setRandomHand' then
console.log('computer listens');
let choosedHand = Math.round(Math.random() * 2);
this.activeHand = this.hands[choosedHand].name;
this.playIcon = this.hands[choosedHand].icon;
this.$emit('computerChoosedHand', this.activeHand.toLowerCase());
}
// shuffleAnimation () {
// setInterval(() => {
// let shuffle = Math.round(Math.random() * 2)
// this.activeHand = this.hands[shuffle].name
// this.playIcon = this.hands[shuffle].icon
// }, 100)
// }
}
};
</script>
<style lang="scss">
#computer .far {
transform: rotate(-90deg);
}
</style>
other child of GameField - Human.vue
<template>
<div id="human">
<div class="text-center">
<div class="h2 mb-5">Human</div>
<i class="far" :class="playIcon"></i>
<div class="h3 mt-4">{{ activeHand }}</div>
<div class="row select-hand mt-4">
<div class="col-md-4">
<i class="far fa-hand-rock" @click="setHand(hands[0])"></i>
</div>
<div class="col-md-4">
<i class="far fa-hand-paper" @click="setHand(hands[1])"></i>
</div>
<div class="col-md-4">
<i class="far fa-hand-scissors" @click="setHand(hands[2])"></i>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data: () => {
return {
winCounter: 0,
activeHand: 'Choose a Hand',
playIcon: '',
hands: [
{
name: 'Rock',
strength: 'scissor',
weakness: 'paper',
icon: 'fa-hand-rock'
},
{
name: 'Paper',
strength: 'rock',
weakness: 'scissor',
icon: 'fa-hand-paper'
},
{
name: 'Scissor',
strength: 'paper',
weakness: 'rock',
icon: 'fa-hand-scissors'
}
]
}
},
methods: {
setHand (hand) {
this.activeHand = hand.name
this.playIcon = hand.icon
this.$emit('humanChoosedHand', this.activeHand.toLowerCase())
}
}
}
</script>
<style lang="scss">
#human .far {
transform: rotate(90deg);
}
</style>
Maybe it is not possible to listen to a event and then $ref.component.callFunction()
?
Upvotes: 2
Views: 5669
Reputation: 73377
Gamefield
is not listening properly, since you are missing some code in your tag. You need to add @humanChoosedHand
in your tag:
<Human @humanChoosedHand="triggerComputer"></Human>
which now correctly listens to changes of humanChoosedHand
Now triggerComputer
can trigger the computer function from Gamefield
:
triggerComputer() {
this.$refs.computer.setRandomHand();
}
therefore remove v-on:humanChoosedHand="startGame()"
from the Computer
tag.
Here's a SANDBOX to play with.
Upvotes: 1