web component学习使用

Web Components提供了一套原生API,用于创建可复用的自定义元素,类似于Vue组件。主要涉及Custom Element、Shadow DOM和Template/Slot。Custom Element通过`customElements.define`定义,Shadow DOM用于封装组件并隔离样式。创建Web Components的流程包括创建模板、生成Shadow DOM以及处理属性监听和事件传递。由于兼容性问题,实际应用需注意浏览器支持。
摘要由CSDN通过智能技术生成

# Web Components

Web Components是一套原生的,允许我们自定义一套可重用有相应功能的元素的组件。

利用它,可以实现类似vue组件的可复用模块。

缺点: 兼容不好

相关知识:

1. Custom Element: 自定义元素

customElements的通过define方法来自定义元素

   - 接受两个参数

   - 第一个参数,自定义元素名

   - 第二个元素,自定义元素的模板对象

   - 例子: customElements.define('test-button', TestButton)

2. shadow Dom(影子DOM): 影子DOM将我们的自定义元素封装起来,并插入到文档中(影子dom中的内容是跟主文档隔开的)

3. template(模板)和 slot(插槽)

---

## 创建一个web Components的具体流程

1. 创建两个模板test-collapse 和 test-collapse-item

<template id="test-collapse">

  <slot></slot>

</template>

<template id="test-collapse-item">

  <div class="title">title内容</div>

  <div class="content"><slot></slot></div>

</template>

2. 根据模板创建shadow Dom并使其在文档中生效

难点: 是需要知道相关的api

// 定义需要监听的属性

// 比如监听active属性的变化

  static get observedAttributes() {

    return ['active'];

  }

// 生命周期函数,监听的属性变化时触发

      attributeChangedCallback(key, oldValue, newValue) {

        if(key === 'active') {

          this.activeList = JSON.parse(newValue)

          // 属性变化后,触发自定义的方法

          this.render()

        }

      }

// 父组件传值给子组件是通过设置子组件的属性,子组件监听属性变化即可

// 子组件传值给父组件,是通过派发父组件的自定义事件

 - 父组件自定义监听事件

    testCollapse.addEventListener('nameChange', (e) => {

      let {isShow, name} = e.detail

      if(isShow) {

        let index = defaultAtiveList.indexOf(name)

        if(index != -1) {

          defaultAtiveList.splice(index, 1)

        }

      } else {

        defaultAtiveList.push(name)

      }

      testCollapse.setAttribute('active', JSON.stringify(defaultAtiveList))

    })

 - 子组件派发事件
 

  document.querySelector('test-collapse').dispatchEvent(new CustomEvent('nameChange', {

    detail: {

      name: that.name,

      isShow: that.isShow

    }

  }))


 

TestCollapse

class TestCollapse extends HTMLElement {

      // 定义需要监听的属性

      static get observedAttributes() {

        return ['active'];

      }



      constructor() {

        super()

         // 创建shadow dom

        var shadow = this.attachShadow({mode: 'open'});

        // attachShadow函数的mode配置有两个值可选 open|close

        // open 表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM

        // 获取模板

        var tempTmp = document.querySelector('#test-collapse') 

        // 拷贝模板内容

        // template.content可以获取到模板的内容

        var cloneTemp = tempTmp.content.cloneNode(true) // 传参true是不单只拷贝子元素,而且还拷贝模板元素本身

        

        var style = document.createElement('style')

        style.textContent = `

          test-collapse {

            display: flex;

            flex-direction: column;

          }

        `

        shadow.appendChild(cloneTemp)

        shadow.appendChild(style)



        this.activeList = []



        // 监听slot插槽内容的变化,插槽内容变化,更新内容

        shadow.addEventListener('slotchange', ()=> {

          this.render()

        })



      }



      // 生命周期函数,监听的属性变化时触发

      attributeChangedCallback(key, oldValue, newValue) {

        if(key === 'active') {

          this.activeList = JSON.parse(newValue)

          // 属性变化后,触发自定义的方法

          this.render()

        }

      }



      render() {

        this.querySelectorAll('test-collapse-item').forEach(item => {

          item.setAttribute('active', JSON.stringify(this.activeList))

        })

      }

    }


TestCollapseItem

    class TestCollapseItem extends HTMLElement {

      static get observedAttributes() {

        return ['active', 'title', 'name']

      }

      constructor() {

        super()

        var shadow = this.attachShadow({mode: 'open'});

        // 获取模板

        var tempTmp = document.querySelector('#test-collapse-item') 

        // 拷贝模板内容

        // template.content可以获取到模板的内容

        var cloneTemp = tempTmp.content.cloneNode(true) // 传参true是不单只拷贝子元素,而且还拷贝模板元素本身

        

        var style = document.createElement('style')

        style.textContent = `

          .content {

            background: #999;

          }

        `

        shadow.appendChild(cloneTemp)

        shadow.appendChild(style)



        this.isShow = true

        this.titleEle = shadow.querySelector('.title')

        this.titleEle.addEventListener('click', () => {

          let that = this

          document.querySelector('test-collapse').dispatchEvent(new CustomEvent('nameChange', {

            detail: {

              name: that.name,

              isShow: that.isShow

            }

          }))

        })

        

      }

      

      attributeChangedCallback(key, oldValue, newValue) {

        switch (key) {

          case 'active':

            this.activeList = JSON.parse(this.getAttribute(key))

            break;

          case 'title':

            this.titleEle.innerHTML = this.getAttribute(key)

            break;

          case 'name':

            this.name = this.getAttribute(key)

          default:

            break;

        }



        if(this.activeList && this.name) {

          this.isShow = this.activeList.includes(this.name)

          // this.shadowRoot获取影子dom的根元素

          this.shadowRoot.querySelector('.content').style.display = this.isShow ? 'block': 'none'

        }

      }

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值