你不知道的WebComponent

本文介绍了如何通过继承HTML实现组件化,包括通过`MyImg`实例展示继承`img`元素的方法,以及如何创建独立组件如`MyCom`,涉及样式隔离、插槽和自定义事件。最后展示了如何制作简易Dialog组件。

1、原生也有组件?

现在Vue、React的大规模流行。前端组件化已经成为潮流,但是原生的组件又有多少人了解了。下面通过几个代码示例,让你快速了解原生怎么写组件。

2、通过继承 HTML 实现组件

代码demo示例

// 通过继承 HTMLImageElement 实现组件化
class MyImg extends HTMLImageElement {
  constructor() {
    super()
    const src = 'https://resource.ttplus.cn/publish/app/pics/2019/04/18/233772/76d96560-7211-483d-988c-dc00d8391f41.jpg'
    setTimeout(() => {
      // this 指向继承后的新组件
      this.src = src
    }, 1000)
  }
}

// 组件名字 继承后的类 需要继承的标签
customElements.define('my-img', MyImg, {
  extends: 'img',
})

使用的时候只需要在你继承的标签中,is="你的组件名" 即可

<img is="my-img" />

3、独立的组件

代码demo示例

demo2.html

<style>
  /* 样式隔离,无法操作 MyCom 内部的样式 */
  .my_com_main {
    background: pink;
  }
</style>

<my-com class="my_com" cusAttr="我是自定义属性">
  <span slot="middle">我是主要内容</span>
  <h2 slot="bottom">我是底部</h2>
  <div slot="head">我是头部插槽</div>
</my-com>
<script type="module" src="./demo2.js"></script>

MyCom.js

const template = document.createElement('template')
template.innerHTML = `
<style>
  .my_com_wrapper {
    border: 1px solid red;
  }
  .my_com_main {
    height: 100px;
    background: skyblue;
  }
</style>
<div class="my_com_wrapper">
  <header>
    <slot name="head"></slot>
  </header>
  <main class="my_com_main">
    <slot name="middle"></slot>
  </main>
  <footer>
    <slot name="bottom"></slot>
  </footer>
</div>
`
class MyCom extends HTMLElement {
  constructor() {
    super()
    // 获取自定义组件的属性
    console.log(this.getAttribute('class'))
    console.log(this.getAttribute('cusAttr'))
    // 使用 attachShadow 与外面样式进行隔离
    const sd = this.attachShadow({ mode: 'open' })
    sd.appendChild(template.content)
  }
}

customElements.define('my-com', MyCom)

demo2.js

import './MyCom.js'

const myComEl = document.querySelector('.my_com')
// 当 attachShadow 的 mode 为 open 时,可以获取 shadowRoot 的内容并且操作。
// 如果 mode 为 closed 则无法获取该节点信息
console.log(myComEl.shadowRoot)
const myColElChildren = myComEl.shadowRoot.children
![...myColElChildren].forEach(el => (el.style = 'font-size: 40px;'))

4、如何实现自定义事件

代码demo示例

通过 EventTarget 添加自定义事件。在通过 dispatchEvent 触发 CustomEvent 事件。

<button id="btn_a">自定义事件a</button>
<button id="btn_b">自定义事件b</button>
<script type="module">
  // 创建事件
  const obj = new EventTarget()
  // 添加事件
  obj.addEventListener('a', () => alert('触发了事件a'))
  obj.addEventListener('b', () => alert('触发了事件b'))
  document.querySelector('#btn_a').onclick = () => {
    obj.dispatchEvent(new CustomEvent('a'))
  }
  document.querySelector('#btn_b').onclick = () => {
    obj.dispatchEvent(new CustomEvent('b'))
  }
</script>

5、实现简易版Dialog组件

由于代码太多,直接放链接了

代码demo示例

6、仓库源码地址

https://github.com/Layouwen/webcomponent-demo

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值