Захват событий из выделенного содержимого в веб-компоненте - PullRequest
3 голосов
/ 05 апреля 2019

У меня есть простой веб-компонент, который содержит <slot>.Он обрабатывает данные формы, и внутри меня есть элементы пользовательского интерфейса, которые генерируют изменения данных / выбранные события.Мне интересно, как веб-компонент может реагировать на события, генерируемые слот-контентом.Что-то вроде этого:

<my-form-handler>
     <my-player-selector player-id="master"></my-player-selector>
     <my-player-selector player-id="challenger"></my-player-selector>
     <my-weapons-selector default="sword"></my-weapons-selector>
</my-form-handler>

Я знаю, что мог бы написать <my-form-handler ondataSelected="someFunction">, предполагая, что элементы селектора генерируют dataSelected событий.Но для этого нужно, чтобы код содержался на содержащей странице, а не my-form-handler.

Я не использую какой-либо фреймворк (Vue, Angular, React), просто ванильный JS.

1 Ответ

3 голосов
/ 05 апреля 2019

Вы можете определить в своем пользовательском элементе <my-form-handler> обработчик в constructor() или в методе connectedCallback().

customElements.define( 'my-form-handler', class extends HTMLElement {
    conectedCallabck() {
        this.addEventListener( 'dataSelected', dsHandler )

        function dsHandler( ev ) {
             console.log( ev.type, ev.target.textContent )
        }
    }
} )

Конечно, вы можете использовать функцию стрелки, если хотите, чтобы this относится к объекту пользовательского элемента:

let dsHandler = ev => {
    console.log( ev.type, ev.target.textContent )
}
this.addEventListener( 'dataSelected', dsHandler )

Вы также можете определить встроенный обработчик:

this.addEventListener( 'dataSelected', ev => 
    console.log( ev.type, ev.target.textContent )
)

Примечание: если вы хотите, чтобы обработчик событий был методом пользовательского элемента,вам нужно будет использовать bind(this), чтобы убедиться, что он все еще может обращаться к объекту пользовательского элемента.

customElements.define( 'my-form-handler', class extends HTMLElement {
    conectedCallabck() {
        this.addEventListener( 'dataSelected', this.dsHandler.bind( this ) )
    }
    dsHandler( ev ) {
        console.log( 'recever: %s / emitter: %', this.localName, ev.target.textContent )
    }
} )

В качестве альтернативы, вы можете выбрать централизованное решение с помощью интерфейса handleEvent():

1 Установите сам пользовательский элемент в качестве слушателя:

this.addEventListener( 'dataSelected', this )

2 Реализуйте метод handleEvent():

handleEvent( ev ) {
    switch( ev.type ) {
        case 'dataSelected':
            console.log( 'recever: %s / emitter: %', this.localName, ev.target.textContent )
            break
   }
}

Ниже бегущего фрагмента:

customElements.define( 'my-form-handler', class extends HTMLElement {
    constructor() {
        super()
        this.addEventListener( 'dataSelected', this )
    }
    handleEvent( ev ) {
        console.log( ev.type, ev.target.textContent )
    }
} )

customElements.define( 'my-player-selector', class extends HTMLElement {
    constructor() {
        super()   
        this.addEventListener( 'click', () =>
          this.dispatchEvent( new CustomEvent( 'dataSelected', { bubbles: true } ) )
        )
    }    
} )
<my-form-handler>
     <my-player-selector player-id="master">master</my-player-selector>
     <my-player-selector player-id="challenger">challenger</my-player-selector>
     <my-weapons-selector default="">sword</my-weapons-selector>
</my-form-handler>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...