Shadow DOM 中的属性不会改变

Attribute doesnt change inside ShadowDOM

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

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;

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

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

设置值后重建 html
this.connectedCallback();

确保输入字段也包含更新后的值。
或者你需要想办法 select 并单独更新输入字段。或者只是回忆一下我提到的 connectedCallback() 方法。

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

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

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

value 属性设置为

<vi-textfield value="[val]">

不是

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

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

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

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

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