1

我有以下代码,它创建了一个用 Shadow DOM 封装的自定义元素:

'use strict'
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {

    var root = this.createShadowRoot();
    var divEl = document.createElement('div');
    divEl.setAttribute("id", "container");
    divEl.innerHTML =
        "<input id='input' type='text'>"
      + "<br>"
      + "Result: <span id='result'></span>"
      + "<br><button onclick='performTask()'>Run</button>";
    root.appendChild(divEl);

};
document.registerElement('custom-ele', {
    prototype: proto
});

这个想法是,当单击“运行”时,将从输入元素中获取输入并进行处理(在 performTask() 中),然后将输出放入“#result”中。我的两个问题是:

  1. 如何从 Shadow DOM 的输入字段中获取值?
  2. 我如何将输出放入#result?

以前的 堆栈溢出帖子看起来可以回答我的问题,但是所有建议的链接都不再有效,所以我想知道是否有人可以指出我正确的方向:)

PS 我宁愿不使用模板,因为并非所有浏览器都支持 HTML 导入,我希望我的所有自定义元素代码都包含在一个文件中。

4

2 回答 2

2

关闭

您可以使用querySelectorShadow DOM 上的方法root来获取内部元素:

'use strict'
var proto = Object.create( HTMLElement.prototype )
proto.createdCallback = function ()
{
    //HTML ROOT
    var root = this.createShadowRoot()
    root.innerHTML = "<input id='input' type='text'>"
        + "<br>"
        + "Result: <span id='result'></span>"
        + "<br><button>Run</button>"

    //UI
    var buttonEle = root.querySelector( "button" )
    var inputEle = root.querySelector( "input" )
    var spanEle = root.querySelector( "#result" )
    buttonEle.onclick = function ()
    {
        var input = inputEle.value
        // do some processing...
        spanEle.textContent = input
    } 
}
document.registerElement( 'custom-ele', { prototype: proto } )

注意:您可以template在同一页面中使用没有 HTML 导入。请参阅以下代码段:

<html>

<body>
  <custom-ele></custom-ele>

  <template id="custelem">
    <input id='input' type='text'>
    <br>Result:
    <span id='result'></span>
    <br>
    <button>Run</button>
  </template>

  <script>
    var proto = Object.create(HTMLElement.prototype)
    proto.createdCallback = function() {
      //HTML ROOT
      var root = this.createShadowRoot()
      root.innerHTML = custelem.innerHTML

      //UI
      var buttonEle = root.querySelector("button")
      var inputEle = root.querySelector("input")
      var spanEle = root.querySelector("#result")
      buttonEle.onclick = function() {
        var input = inputEle.value
          // do some processing...
        spanEle.textContent = input
      }
    }
    document.registerElement('custom-ele', {
      prototype: proto
    })
  </script>


</body>

</html>

没有关闭

如果你不想使用闭包,你可以声明一个handleEvent在你的自定义元素上调用的方法,并添加一个事件监听器来重定向它:

proto.createdCallback = function ()
{
    //HTML ROOT
    var root = this.createShadowRoot()
    root.innerHTML = custelem.innerHTML

    //EVENT
    var buttonEle = root.querySelector( "button" )
    buttonEle.addEventListener( "click", this )
}

proto.handleEvent = function ( ev )
{
    var inputEle = this.shadowRoot.querySelector( "input" )
    var spanEle = this.shadowRoot.querySelector( "#result" )
    // do some processing...
    spanEle.textContent = inputEle.value
}
于 2016-01-05T16:19:23.940 回答
2

原来你可以向影子根本身添加函数,然后你可以在影子根上调用 this.parentNode.fn() 直接孩子访问shadowRoot ...

proto.createdCallback = function() {

    let root = this.createShadowRoot();

    root.innerHTML = "<input id='input' type='text'>"
        + "<br>"
        + "Result: <span id='result'></span>"
        + "<br><button onclick='this.parentNode.process()'>Run</button>";

    this.shadowRoot.process = function() {
        let spanEle = this.querySelector('span');
        let inputEle = this.querySelector('input');
        spanEle.textContent = performAlgorithm(inputEle.value.split(','));
    };
};
document.registerElement('custom-ele', { prototype: proto });

(感谢 MarcG 给了我初步的见解)

于 2016-01-03T22:17:54.267 回答