首页 > 解决方案 > 当组件的属性发生更改时,如何重新渲染组件(webcomponents)

问题描述

这是我的提交按钮组件:

class SubmitButton extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
        this.isLoading = this.getAttribute('loading') === 'true';
        console.log('isLoading: ', this.isLoading);
        this.button = `<button>Go</button>`;
        this.spinner = `
            <svg class="spinner" viewBox="0 0 50 50">
                <circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
            </svg>`
    this.innerHTML = `
      <style>      
            button {
                margin-left: 1rem;
            }

            .spinner {
              // animations and stuff
            }
      </style>
            ${this.isLoading ? this.spinner : this.button}
`;
  }
}

customElements.define("submit-button", SubmitButton);


但是,当我使用 js 动态更改属性时(即:获取完成),我调用它<submit-botton loading="true"></submit-button>时,按钮不会重新呈现自身。

反正有没有让它重新渲染?

我正在使用以下代码更改属性的值:

const button = document.querySelector('submit-button');
button.loading = true;
// do some fetching
button.loading = false;

编辑:这是使用 changedAttributes 处理程序的更新,但它仍然不起作用:

class SubmitButton extends HTMLElement {
  constructor() {
    super();
        this.isLoading = this.getAttribute('loading') === 'true';
  }

    static get observedAttributes() {
        return ['loading'];
    }

     get loading() {
             return this.isLoading;
     }

     set loading(val) {
            this.isLoading = val === 'true';
     }

    render() {
        this.button = `<button>Go</button>`;
        this.spinner = `
            <svg class="spinner" viewBox="0 0 50 50">
                <circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
            </svg>`
    this.innerHTML = `
      <style>      
            button {
                margin-left: 1rem;
            }

            .spinner {
                animation: rotate 2s linear infinite;
                z-index: 2;
                width: 4rem;
                height: 4rem;
                margin-left: 1rem;
            }

            .path {
                stroke: #633;
                stroke-linecap: round;
                animation: dash 1.5s ease-in-out infinite;
            }

            @keyframes rotate {
                100% {
                    transform: rotate(360deg);
                }
            }

            @keyframes dash {
                0% {
                    stroke-dasharray: 1, 150;
                    stroke-dashoffset: 0;
                }
                50% {
                    stroke-dasharray: 90, 150;
                    stroke-dashoffset: -35;
                }
                100% {
                    stroke-dasharray: 90, 150;
                    stroke-dashoffset: -124;
                }
            }
      </style>
            ${this.isLoading ? this.spinner : this.button}
`;

    }

  connectedCallback() {
        console.log('isLoading: ', this.isLoading);
        this.render();
    }

    attributeChangedCallback(name, oldValue, newValue) {
        console.log('attr changed: ',name, oldValue, newValue);
        this.render();
  }
}

customElements.define("submit-button", SubmitButton);

标签: javascriptweb-component

解决方案


这很有趣,谢谢你提出这个问题。我从https://developers.google.com/web/fundamentals/web-components/customelements借了一些代码并创建了这个JSFiddle

基本上,我并不担心 is或,loading只是检查了属性的存在:"true""false"

get loading() {
  return this.hasAttribute('loading');
}

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

在那之后,这是一个检查的问题this.loading。请务必检查 JSFiddle。


推荐阅读