代码之家  ›  专栏  ›  技术社区  ›  chovy

当组件的属性发生更改时,如何重新呈现组件(webcomponents)

  •  0
  • chovy  · 技术社区  · 3 年前

    这是我的提交按钮组件:

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

    我称之为 <submit-botton loading="true"></submit-button> 然而,当我使用js动态更改属性(即:fetch finishes)时,按钮不会重新呈现自己。

    有没有办法让它重新渲染?

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

    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);
    
    
    0 回复  |  直到 3 年前
        1
  •  2
  •   annoyingmouse    3 年前

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

    基本上,我不担心 loading "true" "false" ,仅检查属性的存在:

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

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