#web-component #stenciljs
Вопрос:
Пример Stencil.js веб-компонент:
import { Component, ComponentInterface, Event, EventEmitter, h, Host } from "@stencil/core";
@Component({
tag: 'foo-testwebcomponent'
})
export class TestWebComponent implements ComponentInterface {
@Event({
eventName: 'foo-click',
cancelable: true
}) fooClick: EventEmitter;
fooClickHandler() {
this.fooClick.emit();
}
render() {
return(
<Host>
<a href="#"
onClick={this.fooClickHandler.bind(this)}
>Testing</a>
</Host>
)
}
}
HTML:
<foo-testwebcomponent id="test"></foo-testwebcomponent>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('test')
.addEventListener('foo-click', event => {
event.preventDefault();
console.log(`Foo Test Web Component clicked!`);
});
});
</script>
Проблема:
В реализации HTML параметр запретить по умолчанию не останавливает работу ссылки.
Вопрос:
Как я могу разрешить конечному пользователю моего веб-компонента запретить использование по умолчанию и запретить работу ссылки?
Я знаю, что могу добавить preventDefault()
fooClickHandler()
(см. Ниже), но мне это кажется странным. Я хотел бы передать управление конечному пользователю веб-компонента.
@Event({
eventName: 'foo-click',
cancelable: true
}) fooClick: EventEmitter<MouseEvent>;
fooClickHandler(event: MouseEvent) {
event.preventDefault();
this.fooClick.emit();
}
Ответ №1:
Есть два отдельных события:
- Событие щелчка, инициированное пользователем
- Ваше
fooClick
пользовательское мероприятие
В вашем примере вы вызываете preventDefault()
пользовательское событие, но вам нужно вызвать его в исходном событии щелчка, чтобы предотвратить переход по ссылке.
Я знаю два способа добиться этого:
1. Отследите, отменено ли ваше пользовательское событие
Вы можете проверить, вызывал ли пользователь preventDefault()
ваше пользовательское событие, используя это defaultPrevented
свойство. Обработчик fooClick
событий может оставаться прежним.
fooClickHandler(clickEvent: MouseEvent) {
const customEvent = this.fooClick.emit();
if (customEvent.defaultPrevented) {
clickEvent.preventDefault();
}
}
Ознакомьтесь с этой онлайн-демонстрацией.
2: Передайте событие щелчка
Передайте fooClick
событие щелчка обработчику событий, чтобы пользователь мог его отменить.
fooClickHandler(clickEvent: MouseEvent) {
this.fooClick.emit({ originalEvent: clickEvent });
}
И в обработчике:
element.addEventListener('foo-click', event => {
event.detail.originalEvent.preventDefault();
console.log(`Foo Test Web Component clicked!`);
});
Комментарии:
1. Спасибо вам за вашу помощь! Мне нравятся оба примера. Я действительно наткнулся
customEvent.defaultPrevented
, но я не был уверен, как это использовать, чтобыhref
предотвратить стрельбу. Спасибо!
Ответ №2:
Одним из способов было бы перегрузить addEventListener
функцию и захватить ссылку на функцию
(нужно еще немного поработать, чтобы заставить его работать с вложенными элементами, вы получите дрейф)
Или используйте пользовательский метод addClick(name,func)
, чтобы пользователь все равно мог добавить любого слушателя
<script>
customElements.define(
"my-element",
class extends HTMLElement {
connectedCallback() {
this.clicked = (evt)=>{
document.body.append("component handler")
}
this.onclick = (evt) => {
this.clicked(evt);
}
}
addEventListener(name, func) {
this.clicked = func;
}
}
);
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('my-element')
.addEventListener('click', event => {
document.body.append(`user handler`);
});
});
</script>
<my-element>Hello Web Components World!</my-element>
Вы также можете использовать старые добрые onevent
обработчики:
<script>
customElements.define(
"my-element",
class extends HTMLElement {
connectedCallback() {
this.onclick = (evt) => console.log("component handler")
}
}
);
document.addEventListener('DOMContentLoaded', () => {
let el = document.querySelector('my-element');
el.onclick = event => console.log(`user handler`, el.onclick);
});
</script>
<my-element onclick="console.log('inline')">Hello Web Components World!</my-element>
Комментарии:
1. Спасибо вам за вашу помощь, я действительно ценю это! 1