什么是web componets, 它的出现是为了什么?

web components旨在提供一套制作可重用的封装性好的自定义元素的标准。

它包括四部分:

customElements -- 这是一个基于CustomeElementRegistry类生成的对象,用于注册自定义元素,如customElements.define('my-popup', MyPop), 并返回已注册的自定义元素的信息。经过注册的元素就可以直接在html页面上像普通元素那样使用了,如<my-popup/>

shadow DOM -- 影子DOM

HTML template -- HTML模板

HTML import -- HTML导入

customElements.define用于注册自定义元素,那什么是自定义元素呢?

自定义元素即为一个class,在这个class里添加各种内置的元素并实现一些逻辑。如果想在页面上使用这个自定义元素,需要用CustomElementRegistry 的define来注册一下。

自定义元素有两种

  1 autonomous custom elements

  extends HTMLElement, 可以通过<popup-info>或doducment.createElement("popup-info")引入到页面

  注册: customElements.define("popup-info", PopupInfo);

  2 customized built-in elements

  继承自基础的html elements,比如div /p/ span等,需要添加is属性来引入到页面,<p is="word-count">或 document.createElement("p", {is:"word-count"})

  注册: customElements.define('expanding-list', ExpandingList, {extends:"ul"});

  很明显的看出来,customize built-in elements注册时,需要提供第三个参数,来表明是继承自谁

自定义元素的生命用期:

  • connectedCallback:当 custom element首次被插入文档DOM时,被调用。
  • disconnectedCallback:当 custom element从文档DOM中删除时,被调用。
  • adoptedCallback:当 custom element被移动到新的文档时,被调用。
  • attributeChangedCallback: 当 custom element增加、删除、修改自身属性时,被调用。这个回调需要自定义组件提示 static get observedAttributes(){return ['属性名','属性名',...];}。如果在组件还没 append到某元素上,此时setAttribute也会触发该事件。

这些都可以在自定义元素的class里直接引入来针对不同的阶段进行相应的业务处理。

Shadow DOM

它是document node的一种。对保证组件的独立,使其行为、样式、事件等不受外部的影响起关键作用。它给自定义组件里的元素提供了一个隐蔽的分离出来的DOM.

与Shadow DOM相关的几个术语:

  • shadow host 是一个普通的dom元素,用来安放shdow dom
  • shadow tree dom树
  • shadow boundary shadow dom的边界,表示shadow dom结束,regular dom开始
  • shadow root shadow tree的根

shadow DOM的基本用法

this.attachShadow({mode:'open'}),将shadow root加到自定义元素上。mode有两个值:open和closed。open的话,在外边也可以访问到组件的shadowRoot,closed的正好相反.

  1. let myShadowDom = myCustomElem.shadowRoot;

 mode为open时myShadowDom可以取到值,并能对里边的元素做操作。mode为close时myShadowDom为null; 

  1. function updateStyle(elem) {
  2. const shadow = elem.shadowRoot; // 访问自定义组件的shadow root
  3. shadow.querySelector('style').textContent = `
  4. div {
  5. width: ${elem.getAttribute('l')}px;
  6. height: ${elem.getAttribute('l')}px;
  7. background-color: ${elem.getAttribute('c')};
  8. }
  9. `; // shadow root有跟document类似的方法如getElementById,querySelector等
  10. }

  

slot和template

在shadow dom中引入slot来增加灵活性。搭配使用template效果更佳。

slot让用户可给向自定义组件里添加自己的标签元素。它通过name属性来指定一个slot,所以组件内的slot的name要唯一。

<template>标签里的代码片断(DocumentFragment)不会被rend到页面上,只能通过javascript的Node.cloneNode克隆出新的DocumentFragment然后后再appendChild或是insertBefore来加来到dom树上。

template里的documentFragment通过HTMLTemplateElement.content来取得。

  1. <template id="element-details-template">
  2. <style>
  3. details {font-family: "Open Sans Light",Helvetica,Arial}
  4. .name {font-weight: bold; color: #217ac0; font-size: 120%}
  5. h4 { margin: 10px 0 -8px 0; }
  6. h4 span { background: #217ac0; padding: 2px 6px 2px 6px }
  7. h4 span { border: 1px solid #cee9f9; border-radius: 4px }
  8. h4 span { color: white }
  9. .attributes { margin-left: 22px; font-size: 90% }
  10. .attributes p { margin-left: 16px; font-style: italic }
  11. </style>
  12. <details>
  13. <summary>
  14. <span>
  15. <code class="name"><<slot name="element-name">NEED NAME</slot>></code> <!--slot->
  16. <i class="desc"><slot name="description">NEED DESCRIPTION</slot></i> <!--slot->
  17. </span>
  18. </summary>
  19. <div class="attributes">
  20. <h4><span>Attributes</span></h4>
  21. <slot name="attributes"><p>None</p></slot> <!--slot ->
  22. </div>
  23. </details>
  24. <hr>
  25. </template>

  

  1. customElements.define('element-details',
  2. class extends HTMLElement {
  3. constructor() {
  4. super(); // constructor里先写上super,this才能被赋值
  5. var template = document
  6. .getElementById('element-details-template')
  7. .content;// template可以通过dom的方法来取到,它的content属性返回的就是内部的DocumentFragment
  8. const shadowRoot = this.attachShadow({mode: 'open'}) // 自定义组件首先要创建shadow,通过appendChild来往shadow里添加标签元素
  9. .appendChild(template.cloneNode(true));
  10. }
  11. })

  

  1. <element-details>
  2. <span slot="element-name">slot</span> <!--通过给标签添加slot="slotName"来将这个标签填充到自定义标签里->
  3. <span slot="description">A placeholder inside a web
  4. component that users can fill with their own markup,
  5. with the effect of composing different DOM trees
  6. together.</span>
  7. <dl slot="attributes"> <!--如果不给名称为attribute的slot写标签的话,会用自定义组件里的该slot内的标签->
  8. <dt>name</dt>
  9. <dd>The name of the slot.</dd>
  10. </dl>
  11. </element-details>

还有一个与此相关的css伪类:define :host :host-context,方法,可以用到时再学习

总结

实现web componets的步骤与方法如下:

https://developer.mozilla.org/zh-CN/docs/Web/Web_Components

学习web components的更多相关文章

  1. web Components 学习之路

    就目前而言,纯粹的Web Components在兼容性方面还有着较为长远的路,这里做个记录总结,以纪念自己最近关于Web Components的学习道路. 参考教材 JavaScript 标准参考教程 ...

  2. 【shadow dom入UI】web components思想如何应用于实际项目

    回顾 经过昨天的优化处理([前端优化之拆分CSS]前端三剑客的分分合合),我们在UI一块做了几个关键动作: ① CSS入UI ② CSS作为组件的一个节点而存在,并且会被“格式化”,即选择器带id前缀 ...

  3. Web Components之Custom Elements

    什么是Web Component? Web Components 包含了多种不同的技术.你可以把Web Components当做是用一系列的Web技术创建的.可重用的用户界面组件的统称.Web Com ...

  4. 【转】Facebook React 和 Web Components(Polymer)对比优势和劣势

    原文转自:http://segmentfault.com/blog/nightire/1190000000753400 译者前言 这是一篇来自 StackOverflow 的问答,提问的人认为 Rea ...

  5. Facebook React 和 Web Components(Polymer)对比优势和劣势

    目录结构 译者前言 Native vs. Compiled 原生语言对决预编译语言 Internal vs. External DSLs 内部与外部 DSLs 的对决 Types of DSLs - ...

  6. Fiori Fundamentals和SAP UI5 Web Components

    这周有位同事邀请我给团队讲一讲SAP技术的演进历史,所以我准备了下面几个主题来介绍. 其中SAP的技术回顾和演进,我的思路就是从前后台两方面分别介绍. 我画了一张非常简单的图: 去年5月我写过一篇文章 ...

  7. Web Components 入门实例教程

    转自阮一峰http://www.ruanyifeng.com/blog/2019/08/web_components.html 组件是前端的发展方向,现在流行的 React 和 Vue 都是组件框架. ...

  8. Web API之Web Components

    本文参考<你的前端框架要被web组件替代了>. 于2011年面世的Web Components是一套功能组件,让开发者可以使用 HTML.CSS 和 JavaScript 创建可复用的组件 ...

  9. Lightning Web Components 安装试用(一)

    Lightning Web Components 简称(lwc) 是一个快速企业级的web 组件化解决方案,同时官方文档很全,我们可以完整的 学习lwc 项目结构 使用npx 官方提供了一个creat ...

随机推荐

  1. springboot的maven配置问题

    我是在idea中配置的中,mac,直接搜的网上最简单的教程,依赖包报错: project structure中引用路径报错 --> maven仓库的路径可能有问题 找不到springapplic ...

  2. 阿里云HttpClient跨天之后解析不了域名

    也许这是一个少见的情况,我使用HttpClient写了一个调用第三方服务的请求,在本机测试和腾讯云上测试都没有问题,但是放到阿里云之后,刚启动的时候是没有问题的,但是每次过零点之后,就会报异常: ja ...

  3. 【JavaScript】JS知识点复习

    1.引入的两种方式:直接在标签里行内js,在body最下端引入. 2.变量的5种类型:number,string,boolean,null,undefined以及一种特殊类型:object 3.变量命 ...

  4. RDLC报表数据集的一个细节,导致错误为 尚未数据源提供数据源实例

    报表中,数据集的名字DataSet_CZ, 这里报表这样加载,视乎是的. reportViewer1.LocalReport.DataSources.Add(new Microsoft.Reporti ...

  5. HBase Thrift过滤语法

    摘抄自hbase ref guide 0.94: 在写本文的时候,hbase ref guide已经更新到1.2及2.0了,但是个人感觉Thrift过滤语法部分写得都没有0.94的好,省掉了examp ...

  6. mysql的group_concat列转行函数

    SELECT auditor,sum(count) total, GROUP_CONCAT(type,'=', count) AS type_count FROM auditor_dm_ol GROU ...

  7. post请求中body数据类型

    1.application/json:json格式,如下: {"input1":"xxx","input2":"ooo" ...

  8. LeetCode 整数反转

    给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: ...

  9. ELK学习笔记之ELK搜集OpenStack节点日志

    模板来自网络,模板请不要直接复制,先放到notepad++内调整好格式,注意缩进 部署架构 控制节点作为日志服务器,存储所有 OpenStack 及其相关日志.Logstash 部署于所有节点,收集本 ...

  10. Parhaps you are running on a JRE rather than a JDK?

    maven项目启动时报错 解决方案: 第一步:在启动项目上右击 第二步:修改JRE为JDK,双击划线部分 第三步:如果没有配置JDK,进行以下操作 第四步:从本地添加JDK 第五步:应用JDK 选择好 ...