&nbs p;
一、了解 HTML UnknownElement元素
在网页中,随便写一个标签,例如:
<usern am e>zhangxinxu</username>
这个 <username> 就是一个HT ML UnknownElement元素。
简单 测试下:
document.querySelector('username') instanceof HTMLUnknownElement; // 返回值是true
在HTML规范中,HTMLUnknownElement元素是一个被认可的合法的元素, CSS 可以无障碍使用,例如:
username { text -t ransform: up PE rcase; }username{text-transform: uppercase;}@H_ 360 _24@
则实时效果如下(用户名大写):
zhangxinxu
HTMLUnknownElement继承HTMLElement中的方法,因此,基本上,常用的HTML方法都是可以畅快使用的,例如,文字变 红色 ,可以直接:
document.querySelector('username').style.color = ' red ';我们不一样
在HTML世界中,HTMLUnknownElement和HTMLDivElement,HTMLSpanElement 等等 都是平级的,平起平坐,都是HTMLElement的子集。那其中有没有什么不一样的地方呢?
区别在于,规范中的一部分HTML元素自己带有一些特殊的属性 或者 方法,例如,表单元素HTMLFormElement元素有 reset() 方法, novalidate 属性。然而,HTMLUnknownElement自己是没有携带任何属性和方法。
这使其是一件好事,我们就可以为HTMLUnknownElement扩展非常私有的方法,而 不用 担心会影响其他元素。例如来说,默认所有HTMLUnknownElement元素的 dis play 计算值都是 inline ,我们可以扩展了 block() 方法使其块状化。
HTMLUnknownElement. PR ototype.block = function () { this.style.display = 'block'; };
此时执行 document.querySelector('username').block() 就可以让 <username> 元素块状化了。
从实用角度讲,基于原型扩展的方法,还不算太智能,要是可以针对不同标签类型进行扩展就更好了,这个后面会介绍。
二、HTMLUnknownElement与自定义元素(Custom Elements)
我之前以为写一个规范以外的 标签元素 就是自定义元素,后来发现不是的。HTMLUnknownElement与自定义元素并不能直接相等,甚至可以说是陌路两人。
W3规范中,对自定义元素的定义是中间必须要有短横线(就是键盘上的减号)连接,并且浏览器也是这么认为的,例如:
document.createElement('username') instanceof HTMLUnknownElement; // 返回值是true document.createElement('user-name') instanceof HTMLUnknownElement; // 返回值是false
从这 一点 看,HTMLUnknownElement一定不是自定义元素,换句通俗的话解释就是“自定义元素不等于随便定义元素”。
虽然都是自己命名的标签,多一个短横和没有短横去区别之大,远不是外面看上去的那点区别。
规范和浏览器为有短横的自定义元素开了很多很棒的特权,可以让我们实现很多很棒的事情!
三、自定义元素(Custom Elements)专场
自定义元素有 哪些 特权呢?我们先从目前可以在实际项目中应用的特性说起。
1. ES6下的继承与自定义HTML元素类型对于自定义元素,规范提供了一套各种HTML特性可继承可扩展的机制,通常使用套路如下:
ES6 class继承; customElements定义元素;先说说目前支持相对较好的 匿名自定义元素 (Autonomous custom elements),也就是继承自HTMElement的用法。
例如,我们实现一个基于 rows 属性多行打点效果的小组件。
注意,下面的演示代码基本上可以作为各类自定义元素(甚至Web component s)使用的 模板 ,很有用,例如,对于学习类似Vue的实时刷新很有帮助,对于学习Shadow DOM 和Web Components也是非常好的案例。以后要实现类似功能,代码拷贝过去,修改修改即可!
class HTMLEllElement extends HTMLElement { // 指定观察的属性,这样attributeChangedCallback才会起作用 stat ic get observedAttributes() { return ['rows']; } constructor() { // constructor中首先第一件事情就是调用 super // super指代了整个prototype或者__proto__指向的对象 // 这一步免不了的 super(); // 创建shadow元素,实际上,从本例要实现的效果讲, // 直接元素上设置也可以,就是HTML丑了点,CSS要放在外部 // 且目前火狐并不支持shadow dom可以不用, // 但一切为了学习,还是展现下现代web组件的实现方式 VAR shadow = this.attachShadow({ // open外部可访问(通过element.shadowRoot),closed则不能 mode: 'open' }); // 文本内容移动到shadow dom元素中 var div = document.createElement('div'); div.innerHTML = this.innerHTML; this.innerHTML = ''; var style = document.createElement('style'); shadow.appendChild(style); shadow.appendChild(div); } // 下面4个方法为常用生命周期 connectedCallback() { console. LOG ('自定义元素加入页面'); // 执行渲染更新 this._updateRendering(); } disconnectedCallback() { // 本例子该生命周期未使用,占位示意 console.log('自定义元素从页面移除'); } adoptedCallback() { // 本例子该生命周期未使用,占位示意 console.log('自定义元素转移到新页面'); } attributeChangedCallback(name, oldValue, newValue) { console.log('自定义元素属性发生变化'); this._rows = newValue; // 执行渲染更新 this._updateRendering(); } // 设置直接get/set rows属性的方法 get rows() { return this._rows; } set rows(v) { this. setattribute ('rows', v); } _updateRendering() { // 根据变化的属性, 改变 组件的UI var shadow = this.shadowRoot; var childNodes = shadow.childNodes; var rows = this._rows; for (var i = 0; i < childNodes.length; i++ ) { if (childNodes[i].nodeName === 'STYLE') { childNodes[i].textContent = `div { display: - webkit -box; -webk IT -line-clamp: ${rows}; -webkit-box-orient: vert ical ; overflow: hidden; }`; } } } } // 定义x-ell标签元素为多行打点元素 customElements. define ('x-ell', HTMLEllElement);
上面代码看上去很长,实际上,也就2部分,一个 class 继承,一个 customElements.define 注册。个中 细节 参见注释,是非常好的学习案例。
那实现了什么效果呢?
很棒的效果,我们直接在页面中写入如下CSS和HTML:
x-ell { display: block; }
<x-ell rows="2">对于现代浏览器,例如webkit内核的浏 .. .组合如下。</x-ell>
这段文字如果超过2行,就会自动在末尾打点。可以看到,页面上没有任何关于打点相关CSS代码的设置,因为全部在自定义HTMLEllElement的时候写在Shadow DOM中了。
如果想要3行打点,也非常简单,直接设置 rows 为 3 即可。我们可以直接手动修改:
<x-ell rows="3">
也可以直接一行JS直接修改属性:
document.querySelector('x-ell').rows = '3';
浏览器会自动渲染成3行文字打点,这就是现代Web Components组件的模样。
眼见为实,您可以狠狠地点击这里:HTML5自定义元素与rows属性直接控制几行打点demo
效果如下Gif 截屏 所示,点击按钮设置 rows 为 3 ,然后3行打点:
rows 属性的表现就好像 <textarea> 元素的 rows 属性一样,修改后直接触发了元素本身UI的变化,而且是实时的。这就是自定义元素,自己定义一个元素,可以和原生元素一样的行为和特性,是不是很酷!
然而兼容性问题不容 忽视 ,如果只考虑ES6继承特性,Firefox,Safari等浏览器也是可以用的,也就是移动端冒进下也是可以使用的。但是自定义元素注册,以及Shadow DOM等特性目前就Ch rom e,And ROI d以及UC等浏览器支持,因此,只能用在一些内部产品(如中后台管 理系 统、内部工具)上。Firefox目前想要支持可以开启实验功能,about: config ,然后设置 dom.webcomponents.customelements.enabled 为 true ,以及 dom.webcomponents.shadowdom.enabled 为 true 。
不过 ,目前Firefox在开发, Edge 在考虑,相信一统江山的时候很快就会到来。
小疑问
customElements.define 自定义元素的时候,标签可否没有短横线,例如:
customElements.define('ell', HTMLEllElement);
答案是,不可以,非短横线自定义元素不认为是合法元素,于是会报错。
下面再看来下目前还没有浏览器支持,但即将支持的 定制内置元素 (Customized built -i n elements)。
什么 意思 呢?上面自定义元素我们都是继承于HTMLElement,实际上,HTMLElement还有非常非常都的内置子集元素,例如上面提到的HTMLDivElement,HTMLSpanElement,HTMLFormElement元素等,每一种类型标签几乎都对应一种内置元素。
所谓“定制内置元素”,指的就是我们的自定义元素继承自这些内置元素。
举个例子,我们希望定义一个继承 <form> 元素的自定义元素,名为 custom-form ,可以这么处理:
class HTMLCustomFormElement extends HTMLFormElement { /* 略 */ } customElements.define('custom-form', HTMLCustomFormElement);
此时,元素 <custom-form> 就有了原生 <form> 的各种属性和方法,例如直接可以使用 reset() 方法重置内部表单元素的值。
这种特性在我们实际开发的时候有什么用呢?
举例来说,在HTML标准中, <form> 元素是不能相互嵌套的,这就导致一个问题,当我们需要局部重置表单内的某些属性值的时候,就不能使用 reset() 方法,因为会误伤其他可能已经输入的值。
例如表单中有很多输入信息,外加一个图片上传。需求是图片选择即上传完毕,此时需要在图片Ajax上传完毕后重置 file 类型 input 的值,IE下值重置不像C hr ome,可以直接设置 value 为空,最佳做法直接 <form> 元素的 reset() 方法,此时,我们就可以在 file 类型 input 外面包一层 <custom-form> 标签,这样,HTML解析时候既没有嵌套问题,又可以使用 reset() 方法对表单元素进行重置。
当然,上面的分析只是理论上的判断,由于目前没有浏览器支持定制内置元素,因此无法断定 是否 真的如此,等回头浏览器支持了,我们再看一看究竟。
2. 自定义元素与HTML import引入自定义元素还可以在HTML模块中使用,目前仅Chrome支持。
大致套路这样的:
HTML模块注册与构建自定义元素; 母页面引入模块; 母页面自定义标签自动组件呈现;例如下面HTML:
<link rel="import" href="module.html"> <zxx-info/>
此时 <zxx-info> 这个元素在页面上呈现出来的效果就是:
那这个module.html究竟做了什么事情呢?就是自定义 <zxx-info> 这个元素。
完整代码如下:
<template id="tpl"> <style> .scope { cont ai n: content; } .scope > img { float: left; m arg in-right: 10px; } .scope > p { mar gin : 0; overflow: hidden; } </style> <div class="scope"> <img src="zxx. jpg "> <p>帅哥一枚!</p> </div> </template> <script> // 定义<zxx-info> class HTMLZxxInfoElement extends HTMLElement { constructor() { super(); // 内部显示信息 this.innerHTML = document. current Script.ownerDocument.querySelector(' # tpl').innerHTML; } }; // 注册 customElements.define('zxx-info', HTMLZxxInfoElement); </script>
两部分,一部分模板,一部分自定义元素定义和注册。都是Web Components中的概念。不展开,大家感受感受即可。
眼见为实,您可以狠狠地点击这里:HTML5自定义元素与HTML import模块引入demo
四、结束语
如果我们平时就使用一些自定义标签定义样式,HTMLUnknownElement用用足矣,简单方便又灵活,什么不符合W3C规范之类的,完全不用在意,规范的哈,你看都有特别的身份标识了,没必要像张灵玉那样过分拘泥,可以学学张楚岚,那才是真智慧。
但是如果你是希望使用自定义标签来开发Web Components组件,得了,标签的短横线还是要加上的。考虑到目前业界几乎没有大规模使用的案例,什么命名规范之类的,其实也不用太在意,怎么开心怎么来就好,你就是先驱者, 别人 按照你的来,久而久之,也就成了约定俗成的规范了。
好,就这些吧。
抛砖引玉,欢迎交流,感谢阅读!
(本篇完)
觉得 可用,就经常来吧! 欢迎评论哦! @L_ 512 _3@,巧夺天工,精雕玉琢。小宝典献丑了!
总结
以上是 为你收集整理的 html5教程-HTMLUnknownElement与HTML5自定义元素的故事 全部内容,希望文章能够帮你解决 html5教程-HTMLUnknownElement与HTML5自定义元素的故事 所遇到的问题。
如果觉得 网站内容还不错, 推荐好友。
查看更多关于html5教程-HTMLUnknownElement与HTML5自定义元素的故事的详细内容...