【问题标题】:Attribute doesnt change inside ShadowDOMShadow DOM 内部的属性不会改变
【发布时间】:2020-04-24 11:41:38
【问题描述】:

在我的以下代码中,值的更改不会更新输入值:为什么?

class textfield extends HTMLElement {

    get value()
    {
        return this.getAttribute("value");
    }

    set value(val)
    {
        this.setAttribute('value', val);
    }

    get readonly() {
        return this.hasAttribute("readonly");
    }

    set readonly(val)
    {
        if (val)
        {
            this.setAttribute("readonly", '');
        }
        else
        {
            this.removeAttribute("readonly");
        }
    }

    static get observedAttributes() {
        return ['readonly', 'value'];
    }

    attributeChangedCallback(name, oldValue, newValue) {
        console.log(name, newValue) ;
    }

    constructor()
    {
        super();
        this.attachShadow({ "mode": "open" });
    }

    connectedCallback()
    {
        this.shadowRoot.innerHTML =  
        /*html*/`
        <div>
            <div>
                Lable
            </div>
            <div>
                <input id="vi-input" type="text" value="${this.getAttribute("value")}" ${ this.hasAttribute("readonly") ? "readonly" : "" } />
            </div>
            <div>
                <span>Error</span>
            </div>
        </div>
        `;
    }
}

window.customElements.define("vi-textfield", textfield);

在我的 index.html 中:

.... 
        <vi-textfield id="myInput" value="2" validation="^\d{4}$" ></vi-textfield>
....

当我通过 JS 更新它时,让我们说:

document.getElementById("myInput").value = 3;

会有attributeChangedCallback的给定console.log,但值本身不会改变......

【问题讨论】:

    标签: javascript html web-component shadow-dom


    【解决方案1】:

    您的 input 不会更新,因为它们是 2 个不同的元素。

     set value(val) {
       this.setAttribute('value', val);
     }
    

    设置value 属性

    &lt;vi-textfield value="[val]"&gt;

    不是上的value属性

    <input id="vi-input" type="text" value="${this.getAttribute("value")}"/>
    

    这是你的元素 shadowDOM 中的另一个元素

    value="${this.getAttribute("value")}" 运行一次,因为connectedCallback() 运行一次

    如果你想设置both,你可以这样做:

     set value(val) {
       this.setAttribute('value', val);
       this.shadowRoot.getElementById("vi-input").setAttribute("value", val);
     }
    

    如果您希望它们同步,您还需要 setAttribute 代码用于输入更改时的value。

    PS。

    set readonly(val) {
            if (val) {
                this.setAttribute("readonly", '');
            } else {
                this.removeAttribute("readonly");
            }
        }
    

    可以写成:

    set readonly(val) {
            this.toggleAttribute("readonly", val);
    }
    

    【讨论】:

      【解决方案2】:

      我猜您正在设置该值,但之后没有做任何事情,至少没有对输入字段进行任何操作。如果您使用浏览器的开发人员工具查看您的元素选项卡,您的元素 vi-textfield 实际上会更新。例如,在通过调用

      设置值之后,您可能能够重建您的 html
      this.connectedCallback();
      

      确保输入字段也包含更新后的值。
      或者您需要找到一种方法来分别选择和更新输入字段。或者只是回忆一下我提到的connectedCallback() 方法。

      或者你可以在你的类中添加某种 MutationObserver (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver),但我认为这不应该像你想象的那样开箱即用:在更新主机的值时,更新影子元素。

      【讨论】:

        猜你喜欢
        • 2019-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 2016-09-18
        • 1970-01-01
        • 2020-10-22
        相关资源
        最近更新 更多