簡體   English   中英

如何從定義組件處理事件並將其傳遞給點亮的組件

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

我正在嘗試使用 lit Element 設計 Web 組件,我需要有關事件的幫助。 正如我們從附加的代碼片段中看到的,我們可以在 html 模板中使用@change="${this.handleEvent}"並處理 lit Element 組件內的函數handleEvent(e){} 通過這種方式,事件僅在點亮的 Web 組件中受到限制和控制。

但是,當其他人使用我們的 Web 組件時,他們無法控制或訪問定義組件中這些事件的值。 例如,如果我們有一個 index.html 文件並且我像<my-element onchange="handleEvent(e)"></my-element>一樣使用它,我應該可以訪問 onchange 事件並在里面調用一個函數僅索引文件。

那么,有沒有辦法實現與常規 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>**

我不明白為什么你需要事件,當點擊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>

通常,使用您自己的自定義元素,您可能還想定義自己的 API 以將其提供給組件的使用者。 這通常還伴隨着定義您自己的組件發出的事件。

看這個簡單的(不亮,但你懂的)例子:

 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>

如果您還想像標准 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>

如果你想監聽元素之外的事件,你應該分派這樣的事件:

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

關於事件的 Lit 文檔很好地概述了如何以及何時調度事件https://lit.dev/docs/components/events/#dispatching-events

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM