嵌套的Web组件和事件处理

Chr*_*son 3 javascript web-component dom-events custom-element

我正在用javascript编写一个记忆游戏.我已经制作了一个用于卡片<memory-card>的网络组件,以及一个用于包含卡片和处理游戏状态的网络组件<memory-game>.的<memory-card>类包含其图像路径,用于当其翻转,默认图像显示为卡的背面,它的导通状态和onclick处理状态和图像之间的切换功能.

所述<memory-game>类具有接收图像,以生成的阵列的设置器<memory-cards>从.处理<memory-game>课堂上更新游戏状态的最佳方法是什么?我应该在那里附加一个额外的事件监听器,<memory-card>还是有更好的方法来解决它?我希望这些<memory-card>元素只能像现在一样处理它们自己的功能,即在点击时根据状态更改图像.

内存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)
Run Code Online (Sandbox Code Playgroud)

内存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)
Run Code Online (Sandbox Code Playgroud)

在Supersharp的回答之后实现自定义事件

memory-card.js(摘录)

connectedCallback () {
    this.addEventListener('click', (e) => {
      this.flipCard()
      const event = new CustomEvent('flippedCard')
      this.dispatchEvent(event)
    })
  }
Run Code Online (Sandbox Code Playgroud)

记忆游戏.js(摘录)

  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)
    })
  }
Run Code Online (Sandbox Code Playgroud)

Sup*_*arp 5

<memory-card>:

  • 使用CustomEvent()和创建自定义事件dispatchEvent()

<memory-game>:

  • 用自己的方式收听自定义事件 addEventListener()

因为卡片嵌套在游戏中,所以事件会自然地冒泡到容器中.

这样,2个自定义元素将保持loosley耦合.