如何向自定义元素添加JavaScript?

如何向自定义元素添加JavaScript?,javascript,web-component,shadow-dom,custom-element,Javascript,Web Component,Shadow Dom,Custom Element,我有以下代码,它创建了一个自定义元素,用shadowdom封装: 'use strict' var proto = Object.create(HTMLElement.prototype); proto.createdCallback = function() { var root = this.createShadowRoot(); var divEl = document.createElement('div'); divEl.setAttribute("id",

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

'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
});
“严格使用”
var proto=Object.create(HTMLElement.prototype);
proto.createdCallback=函数(){
var root=this.createShadowRoot();
var divEl=document.createElement('div');
divEl.setAttribute(“id”、“容器”);
divEl.innerHTML=
""
+“
” +“结果:” +“
运行”; 根追加子项(divEl); }; 文件注册表项('custom-ele'{ 原型:原型 });
其思想是,当单击“Run”时,将从input元素获取输入并进行处理(在performTask()中),然后将输出放入“result”中。我的两个问题是:

  • 如何从阴影DOM中的输入字段中获取值
  • 如何将输出放入#result
  • 上一篇堆栈溢出文章似乎已经回答了我的问题,但所有建议的链接都不再有效,因此我想知道是否有人可以为我指出正确的方向:)


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

    事实证明,您可以将函数添加到影子根本身,然后您只需调用影子根上的.parentNode.fn()命令子级访问影子根

    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 });
    
    proto.createdCallback=function(){
    让root=this.createShadowRoot();
    root.innerHTML=“”
    +“
    ” +“结果:” +“
    运行”; this.shadowRoot.process=函数(){ 设spanEle=this.querySelector('span'); 让inputEle=this.querySelector('input'); spanEle.textContent=performAlgorithm(inputEle.value.split(','); }; }; registerement('custom-ele',{prototype:proto});

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

    结束语

    您可以在阴影DOM
    root
    上使用方法
    querySelector
    获取内部元素:

    '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 } )
    

    我建议在创建或事件委派之后附加事件。嗯,不完全是这样。我的解决方案会让createdCallback被垃圾收集,而你的不会。谢谢你的回复。在代码段中,buttonEle.onclick引用了inputEle,inputEle是createdCallback作用域的一部分。。。这难道不会阻止createdCallback以与我的解决方案相同的方式进行垃圾收集吗?至于模板,我希望我所有的自定义元素代码都被限制在一个文件中,这样我所需要做的就是导入一个文件,然后能够以最小的努力来使用新的元素。@ CODEMEDICIC是的,我的第一个例子是使用闭包上下文,因为我认为它是最好的和最快的方法。我将发布第二个不使用闭包上下文的示例。代码段也被修改以合并javascript和html代码。@MarcG。你错了。您的
    bind
    调用将生成比简单闭包大得多的本地上下文<代码>绑定依赖于闭包本身,因此从GC的角度来看,它没有帮助,对不起。。。另外,当我发帖时,你的回答是不正确和不完整的。实际上,它仍然是有车的,不精确的,而且。。。比我的慢几十倍。准确吗@超级快速:首先,您从我的答案中复制了
    querySelector
    。现在,您更新了答案,以复制我声明的方法
    proto.process
    ,您称之为
    process.handleEvent
    。但是您甚至没有调用
    proto.handleEvent
    函数。请你至少抄袭我所有的答案来纠正你的答案好吗?我认为这是一种相当非正统的做事方式。您正在将方法添加到
    shadowRoot
    对象中,而不是将它们添加到它们所属的自定义元素中。为何另外,如何将事件侦听器添加到按钮,以及在何处定义
    performAlgorithm
    函数?performAlgorithm在同一个文件中,我将process()添加到shadow root的原因是,我可以使用标记,而不是将整个过程与javascript混合在一起,这非常繁琐。在这种情况下没有添加事件侦听器,它是通过onclick属性'this.parentNode.process()'调用的。我无法将它添加到元素中,因为它无法从shadow root中的元素访问(shadow root parentNode为null)@Ashley,出于安全原因,您应该避免使用内联脚本(onclick表达式)。相反,您可以直接在
    createdCallback
    (或
    attachedCallback
    )中定义它:
    this.shadowRoot.querySelector(“按钮”).onclick=function(){this.parentNode.process()}
    ,这是出于安全原因吗?哈哈。@Ashley:我很高兴我能帮上忙。再见。