如何将事件传递给 LitElement 中的 child

How to pass event to a child in LitElement

我想制作一个 drop-down 菜单,当点击输入时,菜单会显示一个切换开关,可以移除或放置 'hidden' class

我有这个方法

toggleMenu() {
    this.classList.toggle("hidden");
}

这里是模板。

render(){
   return html`
       <input @click="${this.toggleMenu}" type="button">
       <ul class="hidden">
           <slot></slot>
       </ul>
   `;
}

一个简单的解决方案是向您的自定义元素添加 属性,例如open,即在您的 toggleMenu 方法中切换:

static get properties() {
  return {
    open: { type: Boolean },
  };
}

constructor() {
  super();
  this.open = false;
}

toggleMenu() {
  this.open = !this.open;
}

然后在您的 render 方法中,根据 this.open 的值设置 <ul>class 属性:

render(){
  return html`
    <button @click=${this.toggleMenu} type="button">Toggle</button>
    <ul class=${this.open ? '' : 'hidden'}>
      <slot></slot>
    </ul>
  `;
}

您可以在下面的代码片段中看到它的工作原理:

// import { LitElement, css, html } from 'lit-element';
const { LitElement, css, html } = litElement;

class DropDownMenu extends LitElement {
  static get properties() {
    return {
      open: { type: Boolean },
    };
  }

  static get styles() {
    return css`
      ul.hidden {
        display: none;
      }
    `;
  }

  constructor() {
    super();
    this.open = false;
  }
  
  toggleMenu() {
    this.open = !this.open;
  }

  render(){
    return html`
      <button @click=${this.toggleMenu} type="button">Toggle</button>
      <ul class=${this.open ? '' : 'hidden'}>
        <slot></slot>
      </ul>
    `;
  }
}
customElements.define('drop-down-menu', DropDownMenu);
<script src="https://bundle.run/lit-element@2.2.1"></script>

<drop-down-menu>
  <li>Item 1</li>
  <li>Item 2</li>
</drop-down-menu>

如果您想对 <ul> 应用额外的 类,您需要查看 classMap 函数,如 in the LitElement docs 所述。


或者,您可以将 reflect: true 添加到 open 属性 声明中,这样您就可以单独使用 CSS 来显示或隐藏 <ul>,而不是比在 render 中设置它的 class:

static get properties() {
  return {
    open: {
      type: Boolean,
      reflect: true,
    },
  };
}

static get styles() {
  return css`
    ul {
      display: none;
    }
    :host([open]) ul {
      display: block;
    }
  `;
}

这是一个工作片段:

// import { LitElement, css, html } from 'lit-element';
const { LitElement, css, html } = litElement;

class DropDownMenu extends LitElement {
  static get properties() {
    return {
      open: {
        type: Boolean,
        reflect: true,
      },
    };
  }

  static get styles() {
    return css`
      ul {
        display: none;
      }
      :host([open]) ul {
        display: block;
      }
    `;
  }

  constructor() {
    super();
    this.open = false;
  }
  
  toggleMenu() {
    this.open = !this.open;
  }

  render(){
    return html`
      <button @click=${this.toggleMenu} type="button">Toggle</button>
      <ul>
        <slot></slot>
      </ul>
    `;
  }
}
customElements.define('drop-down-menu', DropDownMenu);
<script src="https://bundle.run/lit-element@2.2.1"></script>

<drop-down-menu>
  <li>Item 1</li>
  <li>Item 2</li>
</drop-down-menu>

这两种都是常见的方法,最适合您的应用程序的方法取决于您的用例和个人偏好。

我想保持简单,如果您需要对 DOM 节点的引用,则将事件传递给函数,如下所示:

toggleMenu(ev) {
    ev.target.classList.toggle("hidden");
}

以及渲染方法

render(){
   return html`
       <input @click="${(ev)=>{this.toggleMenu(ev)}}" type="button">
       <ul class="hidden">
           <slot></slot>
       </ul>
   `;
}

大功告成