xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

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, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-07-05 17:43  xgqfrms  阅读(166)  评论(1编辑  收藏  举报