javascript - ShadowDOM v1 - 在 lightdom 中更改输入文本

标签 javascript html shadow-dom

我正在尝试监听自定义组件中的文本更改

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <script type="text/javascript" src="component.js"></script>
  </head>
  <body>
    <fancy-p>
      <p>Bar</p>
      <!-- the input should be listened to -->
      <input id="foo" type="text" name="text" placeholder="Hello"></input>
    </fancy-p>
  </body>
</html>

组件.js

customElements.define('fancy-p', class extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }
  get foo() {
    return "foo"
  }
  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
      p {
        color: red;
      }
      :host {
        background-color: blue;
      }
      </style>
      <div data-foo="bar">
        <slot></slot>
      </div>
    `;

    let input = this.querySelector("input");
    console.log("input is:" + input);
  }
});

我尝试监听文本更改并在 connectedCallback 中使用 querySelector,但在 Chrome 70.xx 中,选择器返回 null

似乎当我设置断点时,lightDOM 未填充(即插槽),但我不知道如何向输入添加事件监听器。

我怎样才能做到这一点???

最佳答案

在您的示例中 <input>被放入 <slot>这意味着自定义元素外部的代码拥有 <input>标签。

在下面的代码中,您可以看到我正在使用 document.querySelector在自定义元素之外获取 <input>元素并且不使用 this.querySelectorthis.shadowRoot.querySelector自定义元素代码内部。

customElements.define('fancy-p', class extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }
  get foo() {
    return "foo"
  }
  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
      p {
        color: red;
      }
      :host {
        background-color: blue;
      }
      </style>
      <div data-foo="bar">
        <slot></slot>
      </div>
    `;
    let input = this.shadowRoot.querySelector("input");
    console.log('inside input=',input); // input will be null
  }
});


//Since the `<input>` tag is *owned* by the outside DOM you need to get the events from the outside:


let input = document.querySelector("input");
console.log('outside input=', input);
input.addEventListener('input', () => {
  console.log("input is:" + input.value);
});
<fancy-p>
  <p>Bar</p>
  <input id="foo" type="text" name="text" placeholder="Hello"/></fancy-p>

如果你想通过shadowDOM访问它,那么你需要在shadowDOM中定义它:

customElements.define('fancy-p', class extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }
  get foo() {
    return "foo"
  }
  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
      p {
        color: red;
      }
      :host {
        background-color: blue;
      }
      </style>
      <div data-foo="bar">
        <slot></slot>
        <input id="foo" type="text" name="text" placeholder="Hello">
      </div>
    `;

    let input = this.shadowRoot.querySelector("input");
    console.log('inside input=',input);
    input.addEventListener('input', () => {
      console.log("input is:" + input.value);
    });
  }
});
<fancy-p>
  <p>Bar</p>
</fancy-p>

关于javascript - ShadowDOM v1 - 在 lightdom 中更改输入文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53382342/

相关文章:

javascript - TypeScript 枚举到对象数组

JavaScript:通过字符串内容调用函数,不区分大小写?

html - 此网页如何加载此字体?

javascript - 如何在 Ajax 响应后从 select 标签中获取 html 格式的值?

javascript - React 组件的 Material UI 主题不局限于 Shadow DOM

css - 将 SCSS `@extends` 与深层元素样式一起使用

javascript - Chartjs - 阻塞其他值的堆积条形图

javascript - 使用 vueJS 有条件地设置 href 属性

html - 如何将常见的 CSS 类应用于阴影元素?

javascript - 取一个最大尺寸的div,让它们都一样