I'm writing a memory game in javascript. I have made a web-component for the cards, <memory-card>
and a web-component to contain the cards and handle the game state <memory-game>
. The <memory-card>
class contains its image path for when its turned over, the default image to display as the back of the card, its turned state and an onclick
function to handle switching between the states and the images.
The <memory-game>
class has a setter that receives an array of images to generate <memory-cards>
from. What would be the best method to handle updating the game state in the <memory-game>
class? Should I attach an additional event listener to the <memory-card>
elements there or is there a better way to solve it? I would like the <memory-card>
elements to only handle their own functionality as they do now, ie changing images depending on state when clicked.
memory-game.js
class memoryGame extends HTMLElement {
constructor () {
super()
this.root = this.attachShadow({ mode: 'open' })
this.cards = []
this.turnedCards = 0
}
flipCard () {
if (this.turnedCards < 2) {
this.turnedCards++
} else {
this.turnedCards = 0
this.cards.forEach(card => {
card.flipCard(true)
})
}
}
set images (paths) {
paths.forEach(path => {
const card = document.createElement('memory-card')
card.image = path
this.cards.push(card)
})
}
connectedCallback () {
this.cards.forEach(card => {
this.root.append(card)
})
}
}
customElements.define('memory-game', memoryGame)
memory-card.js
class memoryCard extends HTMLElement {
constructor () {
super()
this.root = this.attachShadow({ mode: 'open' })
// set default states
this.turned = false
this.path = 'image/0.png'
this.root.innerHTML = `<img src="${this.path}"/>`
this.img = this.root.querySelector('img')
}
set image (path) {
this.path = path
}
flipCard (turnToBack = false) {
if (this.turned || turnToBack) {
this.turned = false
this.img.setAttribute('src', 'image/0.png')
} else {
this.turned = true
this.img.setAttribute('src', this.path)
}
}
connectedCallback () {
this.addEventListener('click', this.flipCard())
}
}
customElements.define('memory-card', memoryCard)
implementing the custom event after Supersharp's answer
memory-card.js (extract)
connectedCallback () {
this.addEventListener('click', (e) => {
this.flipCard()
const event = new CustomEvent('flippedCard')
this.dispatchEvent(event)
})
}
memory-game.js (extract)
set images (paths) {
paths.forEach(path => {
const card = document.createElement('memory-card')
card.addEventListener('flippedCard', this.flipCard.bind(this))
card.image = path
this.cards.push(card)
})
}
In the <memory-card>
:
CustomEvent()
and dispatch a custom event with dispatchEvent()
In the <memory-game>
:
addEventListener()
Because the cards are nested in the game, the event will bubble naturally to the container.
This way the 2 custom elements will stay loosley coupled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With