webComponent浅析

了解webComponent概念:

web component是浏览器环境提供的一些新的原生支持的api和模版,它是一套可以支持原生实现组件化的技术;具体涉及到Custom elements(自定义元素)、Shadow DOM(影子DOM)和HTML template(HTML模板)。提供了对布局视图封装能力,可以让DOM、CSSOM和JavaScript在局部环境中运行,使得局部CSS和DOM不会影响到全局。

和目前的前端框架中组件概念有何区别:

组件化的特点:

  • 高内聚,低耦合

  • 标记鲜明易维护

  • 块状接口易扩展

框架组件化的特点:

  • 高效复用

  • 作用域及样式隔离

  • 自定义开发

  • 钩子函数(生命周期)

web component提供了:

1.Custom elements:自定义元素,通过使用对应的api,用户可以在不依赖框架的情况下,开发原生层面的自定义元素,最关键的是,它将包含独立的生命周期,以及提供了自定义属性的监听。这就意味着它也同样具备了较高的可操作性。

2.Shadow DOM:影子dom(最大的特点是不暴露给全局),你可以通过对应的api,将shadow dom附加给你的自定义元素,并控制其相关功能。利用shadow dom的特性,起到隔离的作用,使特性保密,不用再担心所编写的脚本及样式与文档其他部分冲突。

3.HTML模版:通过<template/><slot/>去实现内容分发。

看着好像并没有太大区别,框架有的特点web component也有,web component同样可以满足我们对组件的自定义及复用、与文档其他部分隔离、生命周期的钩子函数,甚至是内容分发等这些诉求。甚至更优一筹,框架在浏览器原生规则之上又一层较高程度的封装,在带来便利高效的同时,不可避免的导致性能的下降。

如何开发一个web component?

一个web component就是一个我们可以在正常dom中使用的自定义元素。自定义元素只需要包含标记结构、样式以及脚本三个部分,最后再对新的自定义元素进行一个注册。简短demo如下:

<body>
    <element-a></element-a>
    <script>
        class ElementA extends HTMLElement {
            constructor() {
                // 必须首先调用 super 方法
                super();
                // 元素的功能代码写在这里
                // 在自定义元素中我们通过Element.attachShadow将一个shadow root附加到任意元素上:
                const shadowRoot = this.attachShadow({ mode: 'open' })
                // 参数mode有两个值
                // open表示可以通过element.shadowRoot访问shadow-dom
                // closed表示不可以从外部获取shadow dom(例如内置元素video)
                // 接着我们就可以为自定义元素添加内容:
                const para = document.createElement('p')
                para.innerHTML = '这是我的自定义元素'
                shadowRoot.appendChild(para)
                // 创建style元素
                const style = document.createElement('style');
                style.textContent = `
                                    p {
                                        color: #ccc;
                                    }
                                    `
                shadowRoot.appendChild(style)
            }

            connectedCallback() {
                // 自定义元素首次插入文档dom时调用
                // 相较于constructor只会执行一次,这个生命周期每次将节点连接到dom时都会调用
                // 可能会执行多次(比如同一个自定义元素remove, append多次)
            }

            disconnectedCallback() {
                // 自定义元素从文档中删除时,调用
            }

            adoptedCallback() {
                // 自定义元素移动到新的文档
                // 比如使用 adoptNode 方法在多iframe下移动元素
            }

            attributeChangedCallback(name, oldVal, newVal) {
                // 属性变更时调用:三个参数对应属性名,旧值,新值
            }
        }
        customElements.define('element-a', ElementA)
        //可以看到define函数包含三个参数:
        // 1.自定义元素名
        // 2.包含自定义元素内容的类
        // 3.可选参数,包含extends属性的对象,指定了创建的元素继承自哪个内置元素,可以继承任意的内置元素
        // 第三个可选参数,需要解释下,我们注册的自定义元素分为两类。
        // 第一种是独立的元素,不继承其他内置的html元素,此时,define函数不传递第三个参数,元素的类继承自HTMLElment类。这样注册的自定义元素,使用方式简单,像普通的html元素一样,例如:<element-a />
        // 第二种是继承自某个内置的html元素,例如p。此时,第三个参数应该是{ extends: 'p' }。同时元素的类也应该继承HTMLParagraphElement类。使用方式是<p is="element-a" />或者在js中document.createElement("p", { is: "element-a" })。
    </script>
</body>

在自定义元素类中定义内容需要借助shadow-dom接口的能力,它提供了封装的能力,将标记结构、样式和行为隐藏到一个独立的dom中,我们操作shdaow-dom和操作常规dom一样(新添加子节点、修改属性等),但是在shadow-dom中的元素和外部的元素互不影响,不能通过document.querySelector方法拿到内部的元素,外部的css样式也不会影响shadow-dom中定义的元素。我们会在里面定义自定义元素的结构,最后将其附加到常规的dom树中。

浏览器内置的一些html元素也有使用它的功能,例如:video input-range等,在 Chrome 中,开发者可以启用开发者工具的Show user agent shadow DOM选项,就能看到这些隐藏的结构。

  

从上可以看出web component的优点还是挺多的:

1.不依赖任何框架,在任何生态中都能运行良好

2.可以在任何一种框架中使用,不用加载任何模块、代码量小

3.易于继承,不需要编译

5.真正的局部CSS作用域

6.在主流浏览器上的支持已经极其良好

同时也会相应的存在一些缺陷:

这里浅谈,就不用demo赘述了

1、组件内部事件回掉

例如,一个弹窗组件中的确定按钮,它的事件是如何触发的呢?

现在方案是 custom element 内部自定义事件 new CustomEvent(),外部用 addEventListener监听,仿佛又回到了原生 JS 写应用的时代

2、组件样式覆盖
对于开发者来说,难免会遇到需要调整组件内部样式的时候。无论你是使用antd、vant还是使用其它组件库,但 web component 的 CSS 防污染机制导致你很难修改内部样式。这需要你付出一些代价来变相的修改内部样式

3、组件内部资源相对路径问题

4、form表单类组件 value 获取问题
Shadow DOM 中包含有 <input>、<textarea> 或 <select> 等标签的 value 不会在 form 表单中自动关联。

5.缺少数据绑定和状态管理也是 WC 存在的缺陷

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值