Web componentd组件内部事件回调及痛点剖析

目录
  • 写在前面
  • WC 到底是什么?
  • 目前存在的缺陷
    • 1、组件内部事件的回调
    • 2、组件样式覆盖
    • 3、组件内部资源相对路径问题
    • 4、form表单类组件 value 获取问题
    • 5、其它
  • 写在后面

写在前面

最近致力于研究 Web components(以下简称WC),并且也初有成效的拿到了一定的结果,但今天想回过头来重新审视一下 WC。

WC 到底是什么?

简单的讲,Web Component 就是把组件封装成 html 标签的形式,并且在使用时不需要写额外的 js 代码。

组件是前端的发展方向,抛开周边技术生态,单纯看 React 和 Vue 都是组件框架。因此,WC 可以视为原生标签的拓展/延伸,说到底,它依旧是一个标签!

类似 <video></video> 标签,相比于原生标签,它多了更为丰富的样式和可操作属性。

谷歌公司由于掌握了 Chrome 浏览器,一直在推动浏览器的原生组件,即 Web Components API。

相比第三方框架,原生组件简单直接,符合直觉,不用加载任何外部模块,代码量小。貌似一切完美,似乎大有可以用来替换React、Vue之类的趋势。

目前存在的缺陷

与其它 web 框架一起使用存在一些小问题,会给开发体验上造成一些困扰。

1、组件内部事件的回调

比如,一个弹窗组件(<my-dialog></my-dialog>)中的确定按钮,那么它的事件是如何触发的呢?

class myDialog extends HTMLElement {
  // ...
  connectedCallback() {
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.innerHTML = `
      <div class="dialog">
        <div class="dialog-content">
          <div class="dialog-body">
            弹窗内容
          </div>

          <button id="okBtn">确定</button>
        </div>
      </div>
    `;
     shadowRoot.querySelector('#okBtn').addEventListener('click', () => {
      // 组件内部定义事件
      this.dispatchEvent(new CustomEvent('okBtnFn'));
    });
  }
}
customElements.define('my-dialog', myDialog);

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

<my-dialog></my-dialog>
<script>
  export default {
    created() {
      document.addEventListener('okBtnFn', function(){
        // 点击弹窗按钮,触发回调事件
      });
    }
  }
</script>

2、组件样式覆盖

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

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

就目前来说,任何直接基于 Custom Element v1, Template 和 HTML Import 的组件都无法做到完全资源独立 —— 在不知道使用方环境且不给使用方增加额外限制的情况下使用内部封装的任何资源文件。比如如果你有一个自定义 icon 组件:

class MyIcon extends HTMLElement {
    static get observedAttributes() { return ['name','size','color'] }
    constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: 'open' });
        shadowRoot.innerHTML = `
            <svg class="icon" id="icon" aria-hidden="true" viewBox="0 0 1024 1024">
                <use id="use"></use>
            </svg>
    }
    attributeChangedCallback (name, oldValue, newValue) {
        if( name == 'name' && this.shadowRoot){
            // 如果使用的项目中,根目录没有 icon.svg 文件,那就 gg
            this.use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', `./icon.svg#icon-${newValue}`);
        }
    }
}
customElements.define('my-icon', MyIcon);

如果使用的项目中,根目录没有 icon.svg 文件,那就 gg。如果你在这里使用 cdn 路径,就会出现跨域问题。

4、form表单类组件 value 获取问题

Shadow DOM 中包含有 <input>、<textarea> 或 <select> 等标签的 value 不会在 form 表单中自动关联。

示例代码:

// web component
class InputAge extends HTMLElement {
  constructor() {
    super();
  }
// connect component
  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'closed' });
    shadow.innerHTML = `<input type="number" placeholder="age" min="18" max="120" />`;
  }
}
// register component
customElements.define( 'input-age', InputAge );

WC 组件被使用后

<form id="myform">
  <input type="text" name="your-name" placeholder="name" />
  <input-age name="your-age"></input-age>

  <button>submit</button>
</form>

<script>
 const form = document.getElementById('myform');

  form.addEventListener('submit', e => {

    e.preventDefault();
    console.log('Submitted data:');

    const data = new FormData(form);
    for (let nv of data.entries()) {
      console.log(`  ${ nv[0] }: ${ nv[1] }`);
    }

  });
</script>

提交的时候无法获取 input-age 的 value。当然会有解决方案,但会很复杂。

5、其它

此外,缺少数据绑定和状态管理也是 WC 存在的缺陷,此处不再赘述。

写在后面

WC 指在丰富 HTML 的 DOM 特性,让 HTML 拥有更强大的复用能力

WC 可以直接当做原生标签,在任何前端框架和无框架中运行

结合当下的主流技术栈来说,WC 当前主要问题在于复杂的组件中,数据通信和事件传递存在一定使用成本

兼容问题,比如可以覆盖内部样式的 :part 方法

以上就是Web componentd组件内部事件回调及痛点剖析的详细内容,更多关于Web componentd事件回调及痛点的资料请关注我们其它相关文章!

(0)

相关推荐

  • 剖析Angular Component的源码示例

    Web Component 在介绍Angular Component之前,我们先简单了解下W3C Web Components 定义 W3C为统一组件化标准方式,提出Web Component的标准. 每个组件包含自己的html.css.js代码. Web Component标准包括以下四个重要的概念: 1.Custom Elements(自定义标签):可以创建自定义 HTML 标记和元素: 2.HTML Templates(HTML模版):使用 <template> 标签去预定义一些内容,但

  • 浅谈Vue内置component组件的应用场景

    官方的说明 渲染一个"元组件"为动态组件.依 is 的值,来决定哪个组件被渲染. <!-- 动态组件由 vm 实例的属性值 `componentId` 控制 --> <component :is="componentId"></component> 具体可以官网文档中的 动态组件 内置的组件component 场景 这里通过一个业务场景来阐述vue内置component组件的应用. 如图所示,这里展示经典注册页面,注册分为邮箱注册

  • 手把手带你封装一个vue component第三方库

    为什么选择自己封装第三方库 最近几个月我司把之前两三年的所有业务都用了 vue 重构了一遍,前台使用 vue+ssr,后台使用了 vue+element,在此过程中封装和自己写了很多 vue component.其实vue 写 component 相当简单和方便,github上有很多的 vue component 都只是简单的包装了一些 jquery 或者原生 js 的插件,但我个人是不太喜欢使用这些第三方封装的.理由如下: 很多第三方封装的组件参数配置项其实是有缺损的.如一些富文本或者图表组件

  • 一个@Component注解引发的大坑

    目录 一个@Component注解引发的大坑 问题是这样的 思考 对spring @component注解的理解 @Component注解的使用 注解的类 测试的类 一个@Component注解引发的大坑 首先,我们这个是用springboot架构来实现的业务 这是项目包结构和配置文件结构 这是定时需要执行的任务 这是我执行PromoCodeCMCJob这个定时器的报错信息 问题是这样的 加了两个MQ之后才报错的这个信息,当我执行启动PromoCodeCMCJob定时任务的时候就报错,报错信息如

  • Web componentd组件内部事件回调及痛点剖析

    目录 写在前面 WC 到底是什么? 目前存在的缺陷 1.组件内部事件的回调 2.组件样式覆盖 3.组件内部资源相对路径问题 4.form表单类组件 value 获取问题 5.其它 写在后面 写在前面 最近致力于研究 Web components(以下简称WC),并且也初有成效的拿到了一定的结果,但今天想回过头来重新审视一下 WC. WC 到底是什么? 简单的讲,Web Component 就是把组件封装成 html 标签的形式,并且在使用时不需要写额外的 js 代码. 组件是前端的发展方向,抛开

  • Yii框架组件和事件行为管理详解

    本文实例讲述了Yii框架组件和事件行为管理.分享给大家供大家参考,具体如下: Yii是一个基于组件.用于开发大型 Web 应用的高性能 PHP 框架.CComponent几乎是所有类的基类,它控制着组件与事件的管理,其方法与属性如下,私有变量$_e数据存放事件(evnet,有些地方叫hook),$_m数组存放行为(behavior). 组件管理 YII是一个纯oop框架,很多类中的成员变量的受保护或者私有的,CComponent中利用php中的魔术方法__get(),__set()来访问和设置属

  • 详解Vue2.0之去掉组件click事件的native修饰

    这个是在组件开发中遇到的问题,当时我在编写button的组件,模板是这样的: <template> <button class="disable-hover button ion-button" :class="[modeClass,typeClass,shapeClass,sizeClass,colorClass,roleClass,strongClass]"> <span class="button-inner"

  • 浅谈Vue2.0父子组件间事件派发机制

    从vue1.x过来的都知道,在vue2.0中,父子组件间事件通信的$dispatch和$broadcase被移除了.官方考虑是基于组件树结构的事件流方式实在是让人难以理解,并且在组件结构扩展的过程中会变得越来越脆落.特别是在组件层级比较深的情况下.通过广播和事件分发的机制,就显得比较混乱了. 官方在废除的同时,也为我们提供了替换方案,包括实例化一个空的vue实例,使用$emit反应子组件上的状态变化 1.使用$emit触发事件 helloWorld.vue作为父组件,dialogConfigVi

  • 深入浅析vue组件间事件传递

    由于新工作需要用vue,所以最近接触最多的也是vue,因为之前一直在用react,所以对于vue上手还是很快的. 我也尽量找一些他们两个的异同点,除了多了一些辅助用的方法以外,最大的不同应该是对于组件间的通信,不仅有props,还有一种事件监听,也是可以通过组件间传递的. 但是,在vue2.+中,vue引入了diff算法和虚拟dom来提升效率.我们知道这些事为了处理频繁更新dom元素所提出的一种优化方案,可频繁变动更新以及事件监听的初始化之间是否会有矛盾,当组件需要变动时,有没有对注册过的事件进

  • Yii框架组件的事件机制原理与用法分析

    本文实例讲述了Yii框架组件的事件机制原理与用法.分享给大家供大家参考,具体如下: 在深入分析 Yii 的运行之前,我们先来看一下 Yii 框架中一个很重要的机制 - 事件. Yii 官方参考文档关于组件事件的解释: ======================================================================= 组件事件是一些特殊的属性,它们使用一些称作 事件句柄 ( event handlers )的方法作为其值. 附加 ( 分配 ) 一个方法到

  • vue组件添加事件@click.native操作

    1,给vue组件绑定事件时候,必须加上native ,否则会认为监听的是来自Item组件自定义的事件 2,等同于在子组件中: 子组件内部处理click事件然后向外发送click事件:$emit("click".fn) <Item @click.native = "shijian()"></Item> 补充知识:vue--组件间(兄弟组件间)事件派发与接收 法一 main.js 在初始化vue之前,给 data 添加一个名为 event 的空v

  • Vue组件之事件总线和消息发布订阅详解

    目录 简介 事件总线 消息的发布订阅 总结 简介 主要介绍事件总线的定义和编写方法和Vue是如何实现消息的订阅与发布的. 事件总线 事件总线是组件间通信的一种方式,适用于任意组件间的通信,比如毫不相干的两个组件.父子组件间.后代组件等等,都能通信. 事件总线有两个特性: 是一个vue组件实例或者一个vue实例,充当一个消息中转站,如果A.B组件想要通信,那么A组件存消息到中转站,B消息拿,或者反过来. 所有组件都要能获取到事件总线. 如果A.B组件间通信,如果A发送数据给B的情况下,需要以下步骤

  • Oracle数据块损坏之10231内部事件不完全恢复

    什么是块损坏: 所谓损坏的数据块,是指块没有采用可识别的 Oracle 格式,或者其内容在内部不一致.通常情况下,损坏是由硬件故障或操作系统问题引起的.Oracle 数据库将损坏的块标识为"逻辑损坏"或"介质损坏".如果是逻辑损坏,则是 Oracle 内部错误.Oracle 数据库检测到不一致之后,就将逻辑损坏的块标记为损坏.如果是介质损坏,则是块格式不正确:从磁盘读取的块不包含有意义的信息.实验:某个分区数据块损坏,不完全恢复此分区表数据.  背景:数据库没有有效

  • Visual Studio 2008 安装失败(“Web 创作组件”无法安装)的解决办法

    Visual Studio 2008 中文正式版可以从微软网站下载试用了,因为之前用英文版感觉比2005快一些,虽然.NET Framework 3.5有点庞大,但还是可以选择开发2.0的项目,因此打算立马安装.试用期为三个月,足够长了,因此安装Team System版本,体验一下新特性.但是最担心的事情还是发生了--无法安装. 问题出在哪里呢?我打算找出原因,试图解决问题. 因为除Visual Studio本身以外,VS安装过程中安装的其他附带安装的组件,基本上都是有单独安装包的.先找到Vis

随机推荐