内容简介:Web Components涉及到的内容还是很多的,每一块都有很多东西可以讲,国外的好多大佬已经产出了好多优秀的文章。 本文照常只是简单了解大致内容而不进入深究,了解且会用即可,浅尝辄止。Web Components本身下面我们走马观花,简单了解一个这四个东西。
Web Components涉及到的内容还是很多的,每一块都有很多东西可以讲,国外的好多大佬已经产出了好多优秀的文章。 本文照常只是简单了解大致内容而不进入深究,了解且会用即可,浅尝辄止。
简介
Web Components本身 不是一个 规范,而是由W3C提出的另外4个规范的合集。这四个规范是:
下面我们走马观花,简单了解一个这四个东西。
HTML Template
之前的页面开发经常的一个做法是把模板放在一个script标签或者隐藏的div中,用的时候通过innerHTML取出,塞进数据, 然后放回页面显示。现在我们可以通过<template>标签存放了。就像这样:
<template id="mytemplate"> <img src="" alt="great image"> <div class="comment"></div> </template> 复制代码
特性检测
要特性检测 <template>,可以创建一个 template 元素并检查它是否拥有 content 属性:
function supportsTemplate() { return 'content' in document.createElement('template'); } if (supportsTemplate()) { // 检测通过! } else { // 使用旧的模板技术或库。 } 复制代码
激活模板
激活模板,即渲染出模板里面的内容。激活模板最简单的方法就是使用 document.importNode() 对模板的 .content 进行深拷贝。 .content 为只读属性,关联一个包含模板内容的 DocumentFragment。
var t = document.querySelector('#mytemplate'); // 在运行时填充 src。 t.content.querySelector('img').src = 'logo.png'; var clone = document.importNode(t.content, true); document.body.appendChild(clone); 复制代码
特点
用 <template> 来包裹内容为我们提供了几个重要属性:
-
它的内容在激活之前一直处于惰性状态。本质上,这些标记就是隐藏的 DOM,它们不会被渲染。
-
处于模板中的内容不会有副作用。脚本不会运行,图片不会加载,音频不会播放,...直到模板被使用。
-
内容不在文档中。在主页面使用 document.getElementById() 或 querySelector() 不会返回模板的子节点。
-
模板能够被放置在任何位置,包括 <head>,<body>,或 <frameset>,并且任何能够出现在以上元素中的内容都可以放到模板中。 注意,"任何位置"意味着 <template> 能够安全的出现在 HTML 解析器不允许出现的位置... 几乎可以作为任何内容模型的子节点, 它也可以作为 <table> 或 <select> 的子元素。
推荐阅读
HTML Imports
之前在页面引入另一个页面或片段往往是通过iframe或者ajax异步加载,而现在我们可以这样做:
在head中引入
<head> <link rel="import" href="/path/to/imports/stuff.html"> </head> 复制代码
js中获取
var content = document.querySelector('link[rel="import"]').import; 复制代码
特性检测
要检测浏览器是否支持导入,可验证 <link> 元素上是否存在 import:
function supportsImports() { return 'import' in document.createElement('link'); } if (supportsImports()) { // 支持导入 } else { // 使用其他方法加载文件 } 复制代码
推荐阅读
Shadow DOM
首先需要设置一下:打开开发者工具,f1打开设置(或右上角三个点),然后勾上Show user agent shadow DOM ——
然后再看下,video标签是这样的 ——
甚至一个普通的input ——
之前被隐藏掉的DOM部分就是shadow DOM。顾名思义,它是其宿主元素的影子,通常用来封装组件的内部结构。
所以像video、audio甚至input都是用简单的元素封装的组件。
这让我想到,我们是不是可以通过修改元素里面的shadow DOM的样式来改变该元素的样式呢? 答案是 —— 是的,但也 不完全 是...
从上图audio标签的结构和浏览器默认样式可以看到,我们可以像这样修改对应的样式:
audio::-webkit-media-controls { ... } 复制代码
就像通过::-webkit-scrollbar改造浏览的滚动条样式那样,
于是,默认的audio样式(新版chrome)——
经过改造后,可以变成这样——
然而并不是所有样式都可以这样覆盖改造,像pseudo="-internal-media-controls-loading-panel"这样以"-internal-"开头的是不可以的。 所以这个做法还是有很大局限性的。
这是我试出来的,并没发现相关标准或依据...:sweat:
这种做法自认为只适合拿来玩玩而已,不适合投入到项目开发中去。一来是因为其局限性太大,二来谁知道啥时候浏览器升级,这些标签的内部结构就又变化了呢, 最重要的是shadow DOM是为web Components而生的,与Custom Elements一起是web Components的重要组成部分,并非用于此“旁门左道”:laughing:。
推荐阅读
- Using shadow DOM
- Shadow DOM 101
- Shadow DOM 201 - CSS and Styling
- Shadow DOM 301 - Advanced Concepts & DOM APIs
Custom Elements
自定义元素,首先有个硬性规定,自定义元素的命名中必须要有中划线“-”,否则便是未知元素了。
自定义元素分为两种 ——
自特性主自定义元素(Autonomous custom elements)
不具备任何已有元素的,其样式和行为完全自定义,如我们要定义一个这样的元素:
<flag-icon country="cn"></flag-icon> 复制代码
通过给属性country赋值来显示对应的国旗。
js的基本结构是这样的
class FlagIcon extends HTMLElement { constructor() { super(); this._countryCode = null; } static get observedAttributes() { return ["country"]; } attributeChangedCallback(name, oldValue, newValue) { // name will always be "country" due to observedAttributes this._countryCode = newValue; this._updateRendering(); } connectedCallback() { this._updateRendering(); } get country() { return this._countryCode; } set country(v) { this.setAttribute("country", v); } _updateRendering() { //... } } //全局注册该元素 customElements.define("flag-icon", FlagIcon); 复制代码
注册后,也通过js创建该元素
const flagIcon = document.createElement("flag-icon"); flagIcon.country = "cn"; document.body.appendChild(flagIcon); 复制代码
自定义内置元素(Customized built-in elements)
继承自已有元素,拥有已有元素的所有特性。
比如我们自定义一个按钮,集成普通按钮所有的特性,但是当点击的时候会有一个动效,就可以这么做 ——
class PlasticButton extends HTMLButtonElement { constructor() { super(); this.addEventListener("click", () => { // 动效逻辑 }); } } 复制代码
不同的是,注册时要加上一个参数
customElements.define("plastic-button", PlasticButton, { extends: "button" }); 复制代码
使用时也稍有不同
<button is="plastic-button">点我!</button> 复制代码
通过js定义元素,则是这样
const plasticButton = document.createElement("button", { is: "plastic-button" }); plasticButton.textContent = "点我!"; document.body.appendChild(flagIcon); 复制代码
生命周期
用过Vue、React等框架的同学对生命周期应该不陌生。同样,自定义元素有4个生命周期:
connectedCallback
元素首次被插入文档DOM时触发
disconnectedCallback
元素从文档DOM中删除时触发
adoptedCallback
元素被移动到新的文档时触发
attributeChangedCallback
元素增加、删除、修改自身属性时触发
推荐阅读
来一个demo
评分组件相信大家都司空见惯了。照葫芦画瓢,我用原生js写了一个Web Components 版的,简单实现了该组件的基本功能。
demo截图:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。