简体   繁体   English

如何从定义组件处理事件并将其传递给点亮的组件

[英]How to handle and pass events to the lit component from defining component

I am trying to design web components using lit Element and I need an help regarding the events.我正在尝试使用 lit Element 设计 Web 组件,我需要有关事件的帮助。 As we can see from the attached snippet we could use @change="${this.handleEvent}" in html template and handle the function handleEvent(e){} inside the lit Element component.正如我们从附加的代码片段中看到的,我们可以在 html 模板中使用@change="${this.handleEvent}"并处理 lit Element 组件内的函数handleEvent(e){} By this the events are limited and controlled only in the lit web components.通过这种方式,事件仅在点亮的 Web 组件中受到限制和控制。

However, when other people use our web components they don't have much control or access to the values over these events in the defining component.但是,当其他人使用我们的 Web 组件时,他们无法控制或访问定义组件中这些事件的值。 For instance, if we have an index.html file and I use it like <my-element onchange="handleEvent(e)"></my-element> , I should have the access to the onchange event and call a function inside the index file only.例如,如果我们有一个 index.html 文件并且我像<my-element onchange="handleEvent(e)"></my-element>一样使用它,我应该可以访问 onchange 事件并在里面调用一个函数仅索引文件。

So, Is there a way to achieve this to the similar behavior of regular html events instead of writing the events which is limited in the lit Element web components.那么,有没有办法实现与常规 html 事件类似的行为,而不是编写在 lit Element web 组件中受限的事件。

 <script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script> <script type="module"> import { LitElement, html, css } from 'https://unpkg.com/lit-element/lit-element.js?module'; class MyElement extends LitElement { static get properties() { return { checked: { type: Boolean, attribute: true } }; } static get styles() { return [ css` div { padding: 10px; width: 90px; border: 2px solid orange; } ` ]; } render() { return html` <div> <input @change="${this.handleEvent}" ?checked="${this.checked}" type="checkbox" /> Checkbox </div> `; } handleEvent(e) { console.log(`Checkbox marked as: ${e.target.checked}`); } } customElements.define('my-element', MyElement); </script> // Index.html <my-element></my-element> // I am expecting to pass an event and handle it in the importing component. // Something like: **<my-element onchange="handleEvent(e)"}></my- element>**

I don't understand why you need Events, when a click on the input can execute either global Functions or local Methods:我不明白为什么你需要事件,当点击input可以执行全局函数或本地方法时:

 customElements.define('foo-bar', class extends HTMLElement { constructor() { let input = document.createElement("input"); input.type = "checkbox"; input.onclick = (evt) => { evt.stopPropagation(); let code = this.getAttribute("onchange"); try { console.log(code); eval(code); // this.onchange() will only execute global functions } catch (e) { console.error(e,code); } } super() .attachShadow({mode: 'open'}) .append(input, "click checkbox to execute ", this.getAttribute("onchange")); } baz() { console.log("Executed baz Method"); } }); function baz() { console.log("Executed baz Function"); }
 <foo-bar onchange="baz()"></foo-bar> <foo-bar onchange="this.baz()"></foo-bar>

Usually with your own custom elements you'll probably also want to define your own API to offer that to consumers of your components.通常,使用您自己的自定义元素,您可能还想定义自己的 API 以将其提供给组件的使用者。 That often also comes with defining your own events which your component emits.这通常还伴随着定义您自己的组件发出的事件。

See this simple (non-lit, but you get the idea) example:看这个简单的(不亮,但你懂的)例子:

 customElements.define('foo-bar', class extends HTMLElement { input = document.createElement('input'); constructor() { super(); this.input.type = 'checkbox'; this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(this.input); this.input.addEventListener('change', this.handleChange.bind(this)); } // replaces the internal change event with an event you publish to the outside world // this event is part of your defined API. handleChange(e) { e.stopPropagation(); const stateChange = new CustomEvent('state-change', { bubbles: true, composed: true, detail: { checked: this.input.checked } }); this.dispatchEvent(stateChange); } }); document.addEventListener('state-change', (e) => { console.log(e.detail); })
 <foo-bar></foo-bar>

If you also want to support declarative event binding as the standard HTML elements do (and using which is widely considered bad practice), you can achieve that using observed attributes:如果您还想像标准 HTML 元素一样支持声明性事件绑定(并且使用它被广泛认为是不好的做法),您可以使用观察到的属性来实现:

 customElements.define('foo-bar', class extends HTMLElement { input = document.createElement('input'); constructor() { super(); this.input.type = 'checkbox'; this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(this.input); this.input.addEventListener('change', this.handleChange.bind(this)); this.declarativeValueChangeListener = this.declarativeValueChangeListener.bind(this); } // replaces the internal change event with an event you publish to the outside world // this event is part of your defined API. handleChange(e) { e.stopPropagation(); const stateChange = new CustomEvent('state-change', { bubbles: true, composed: true, detail: { value: this.input.value } }); this.dispatchEvent(stateChange); } static get observedAttributes() { return [ 'onstatechange' ]; } attributeChangedCallback(attr, oldVal, newVal) { if (oldVal === newVal) return; // nothing changed, nothing to do here if (newVal === null) { // attribute was removed this.removeEventListener('state-change', this.declarativeValueChangeListener) } else { // attribute was added this.addEventListener('state-change', this.declarativeValueChangeListener) } } declarativeValueChangeListener() { const functionStr = this.getAttribute(this.constructor.observedAttributes[0]); eval(functionStr); } }); function baz() { console.log('baz executed through declarative binding of an outside handler!'); }
 <foo-bar onstatechange="baz()"></foo-bar>

If you want to listen to events outside your element, you should dispatch an event like this:如果你想监听元素之外的事件,你应该分派这样的事件:

const event = new Event('my-event', {bubbles: true, composed: true});
myElement.dispatchEvent(event);

The Lit documentation on events gives a good overview of how and when to dispatch events https://lit.dev/docs/components/events/#dispatching-events关于事件的 Lit 文档很好地概述了如何以及何时调度事件https://lit.dev/docs/components/events/#dispatching-events

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM