• Web Components attributeChangedCallback not work bug All In One


    Web Components attributeChangedCallback not work bug All In One

    <!-- demos -->
    <wcui-button></wcui-button>
    <wcui-button type="primary">
      <span slot="text">
        成功按钮
      </span>
    </wcui-button>
    <wcui-button type="warning">
      <span slot="text">
        警告按钮
      </span>
    </wcui-button>
    <wcui-button type="danger">
      <span slot="text">
        危险按钮
      </span>
    </wcui-button>
    
    
    
    <!-- 模版 -->
    <template id="wcui-button-template">
      <style>
        .wcui-button {
          display: inline-block;
          padding: 4px 20px;
          font-size: 14px;
          line-height: 1.5715;
          font-weight: 400;
          border: 1px solid #1890ff;
          border-radius: 2px;
          background-color: #1890ff;
          color: #fff;
          box-shadow: 0 2px #00000004;
        }
        .wcui-button-warning {
          border: 1px solid #faad14;
          background-color: #faad14;
        }
        .wcui-button-danger {
          border: 1px solid #ff4d4f;
          background-color: #ff4d4f;
        }
      </style>
      <div id="wcui-button">
        <slot name="text">默认按钮</slot>
      </div>
    </template>
    
    
    <script>
      // 1. 获取 DOM 模版
      // const template = document.getElementById("wcui-button-template");
      const template = document.querySelector(`#wcui-button-template`);
      console.log('\ntemplate =', template);
      // 2. 继承 HTMLElement 类
      class wcuiButton extends HTMLElement {
        constructor() {
          super();
          // type 属性
          this.types = {
            primary: 'wcui-button',
            warning: 'wcui-button-warning',
            danger: 'wcui-button-danger',
          };
          this.defaultType = 'wcui-button';
          // 开启 Shadow DOM
          const shadow = this.attachShadow({
            mode: 'open',
          });
          // 克隆一份, 防止重复使用造成污染
          const content = template.content.cloneNode(true);
          console.log('\content =', content);
          // 把响应式数据挂到this
          const type = this;
          console.log('\ntype =', type);
          console.log('this.types[type] =', this.types[type]);
          // 获取 template DOM
          this.btn = content.querySelector('#wcui-button');
          console.log('this.btn =', this.btn);
          if(this.types[type]) {
            // this.btn.classList.add(this.types[type]);
            this.btn.className += this.types[type];
          } else {
            this.btn.classList.add(this.defaultType);
            // this.btn.classList.add('bug-style');
          }
          console.log('this.btn.className =', this.btn.className);
          shadow.appendChild(content);
        }
        // observedAttributes
        /*
        static get observedAttributes() {
          return ['type']
        }
        */
        // 生命周期方法
    
        // connectedCallback
        // 当 custom element 首次被插入文档DOM时,被调用。
    
        // disconnectedCallback
        // 当 custom element 从文档DOM中删除时,被调用。
    
        // adoptedCallback
        // 当 custom element 被移动到新的文档时,被调用。
    
        // attributeChangedCallback
        // 当 custom element 增加、删除、修改`自身属性`时,被调用。
        attributeChangedCallback(name, oldValue, newValue) {
          console.log(' prop =', name);
          console.log('oldValue, newValue =', oldValue, newValue);
          this[name] = newValue;
          // update style
          this.render();
          // this.reRender();
        }
        /*
        attributeChangedCallback(prop, oldValue, newValue) {
          console.log(' prop =', prop);
          console.log('oldValue, newValue =', oldValue, newValue);
          this[prop] = newValue;
          // update style
          this.render();
          // this.reRender();
        }
        */
    
        // 渲染
        render() {
          console.log('this.type =', this.type);
          this.btn.className = `wcui-button ${this.types[this.type]}`
        }
        reRender() {
          console.log('this.type =', this.type);
          this.btn.className = `wcui-button ${this.types[this.type]}`
        }
      }
      // ✅  注册自定义组件(Autonomous custom elements / 自主自定义元素)
      window.customElements.define('wcui-button', wcuiButton)
    </script>
    
    

    solution

        // ✅ 必须指定要观察值会变化的 props, 不然 attributeChangedCallback 不会执行
        static get observedAttributes() {
          return ['type']
        }
    
    

    https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks

    注册自定义组件方式

    // ✅ 1. 注册自定义组件(Autonomous custom elements / 自主自定义元素)
    window.customElements.define('wcui-button', wcuiButton)
    
    // ✅ 2. 注册自定义组件(Customized built-in elements / 定制的内置元素)
    window.customElements.define('wcui-button', wcuiButton, { extends: 'div' })
    
    // js 使用方式
    document.createElement("wcui-button")
    
    document.createElement("div", { is: "wcui-button" })
    
    <!--  tag 使用方式 -->
    <wcui-button></wcui-button>
    
    <div is: "wcui-button"></div>
    

    https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#high-level_view

    demo

    // Create a class for the element
    class WordCount extends HTMLParagraphElement {
      constructor() {
        // Always call super first in constructor
        super();
    
        // count words in element's parent element
        const wcParent = this.parentNode;
    
        function countWords(node){
          const text = node.innerText || node.textContent;
          return text.trim().split(/\s+/g).filter(a => a.trim().length > 0).length;
        }
    
        const count = `Words: ${countWords(wcParent)}`;
    
        // Create a shadow root
        const shadow = this.attachShadow({mode: 'open'});
    
        // Create text node and add word count to it
        const text = document.createElement('span');
        text.textContent = count;
    
        // Append it to the shadow root
        shadow.appendChild(text);
    
        // Update count when element content changes
        setInterval(function() {
          const count = `Words: ${countWords(wcParent)}`;
          text.textContent = count;
        }, 200);
      }
    }
    
    // Define the new element
    customElements.define('word-count', WordCount, { extends: 'p' });
    

    view-source:https://mdn.github.io/web-components-examples/word-count-web-component/

    https://mdn.github.io/web-components-examples/word-count-web-component/main.js

    refs

    https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/is

    https://html.spec.whatwg.org/multipage/custom-elements.html



    ©xgqfrms 2012-2020

    www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

    原创文章,版权所有©️xgqfrms, 禁止转载 ️,侵权必究⚠️!


  • 相关阅读:
    大数据
    优化
    gnu
    sed
    hadoop部署
    安装 zookeeper
    ansible
    ssh 配置无密码登录
    未完待续
    解正向代理、反向代理、透明代理
  • 原文地址:https://www.cnblogs.com/xgqfrms/p/16447427.html
Copyright © 2020-2023  润新知