澳门在线威尼斯官方 > 威尼斯澳门在线 > 是个什么样的东西,自定义元素教程

原标题:是个什么样的东西,自定义元素教程

浏览次数:186 时间:2019-11-16

HTML 自定义元素教程

2017/06/22 · HTML5 · 自定义元素

原文出处: 阮一峰   

组件是 Web 开发的方向,现在的热点是 JavaScript 组件,但是 HTML 组件未来可能更有希望。

本文就介绍 HTML 组件的基础知识:自定义元素(custom elements)。

威尼斯澳门在线 1

一、浏览器处理

我们一般都使用标准的 HTML 元素。

XHTML

<p>Hello World</p>

1
<p>Hello World</p>

上面代码中,``

``就是标准的 HTML 元素。

如果使用非标准的自定义元素,会有什么结果?

XHTML

<greeting>Hello World</greeting>

1
<greeting>Hello World</greeting>

上面代码中,`就是非标准元素,浏览器不认识它。这段代码的[运行结果](http://jsbin.com/rifozonomu/edit?html,output)是,浏览器照常显示Hello World`,这说明浏览器并没有过滤这个元素。

威尼斯澳门在线 2

现在,为自定义元素加上样式。

JavaScript

greeting { display: block; font-size: 36px; color: red; }

1
2
3
4
5
greeting {
  display: block;
  font-size: 36px;
  color: red;
}

运行结果如下。

威尼斯澳门在线 3

接着,使用脚本操作这个元素。

JavaScript

function customTag(tagName, fn){ Array .from(document.getElementsByTagName(tagName)) .forEach(fn); } function greetingHandler(element) { element.innerHTML = '你好,世界'; } customTag('greeting', greetingHandler);

1
2
3
4
5
6
7
8
9
10
11
function customTag(tagName, fn){
  Array
    .from(document.getElementsByTagName(tagName))
    .forEach(fn);
}
 
function greetingHandler(element) {
  element.innerHTML = '你好,世界';
}  
 
customTag('greeting', greetingHandler);

运行结果如下。

威尼斯澳门在线 4

这说明,浏览器对待自定义元素,就像对待标准元素一样,只是没有默认的样式和行为。这种处理方式是写入 HTML5 标准的。

“User agents must treat elements and attributes that they do not understand as semantically neutral; leaving them in the DOM (for DOM processors), and styling them according to CSS (for CSS processors), but not inferring any meaning from them.”

上面这段话的意思是,浏览器必须将自定义元素保留在 DOM 之中,但不会任何语义。除此之外,自定义元素与标准元素都一致。

事实上,浏览器提供了一个HTMLUnknownElement对象,所有自定义元素都是该对象的实例。

JavaScript

var tabs = document.createElement('tabs'); tabs instanceof HTMLUnknownElement // true tabs instanceof HTMLElement // true

1
2
3
4
var tabs = document.createElement('tabs');
 
tabs instanceof HTMLUnknownElement // true
tabs instanceof HTMLElement // true

上面代码中,tabs是一个自定义元素,同时继承了HTMLUnknownElementHTMLElement接口。

Web Components 是个什么样的东西

2016/09/04 · HTML5, JavaScript · Web Components

原文出处: teabyii   

前端组件化这个主题相关的内容已经火了很久很久,angular 刚出来时的 Directive 到 angular2 的 components,还有 React 的components 等等,无一不是前端组件化的一种实现和探索,但是提上议程的 Web Components 标准是个怎样的东西,相关的一些框架或者类库,如 React,Angular2,甚至是 x-tag,polymer 现在实现的组件化的东西和 Web Components 标准差别在哪里?我花时间努力地把现有的 W3C Web Components 文档看了下,然后坚强地写下这些记录。

首先我们需要知道,Web Components 包括了四个部分:

  • Custom Elements
  • HTML Imports
  • HTML Templates
  • Shadow DOM

这四部分有机地组合在一起,才是 Web Components。

可以用自定义的标签来引入组件是前端组件化的基础,在页面引用 HTML 文件和 HTML 模板是用于支撑编写组件视图和组件资源管理,而 Shadow DOM 则是隔离组件间代码的冲突和影响。

下边分别是每一部分的笔记内容。

二、HTML import

有了自定义元素,就可以写出语义性非常好的 HTML 代码。

XHTML

<share-buttons> <social-button type="weibo"> <a href="...">微博</a> </social-button> <social-button type="weixin"> <a href="...">微信</a> </social-button> </share-buttons>

1
2
3
4
5
6
7
8
<share-buttons>
  <social-button type="weibo">
    <a href="...">微博</a>
  </social-button>
  <social-button type="weixin">
    <a href="...">微信</a>
  </social-button>
</share-buttons>

上面的代码,一眼就能看出语义。

如果将`元素的样式与脚本,封装在一个 HTML 文件share-buttons.html`之中,这个元素就可以复用了。

使用的时候,先引入share-buttons.html

<link rel="import" href="share-buttons.html">

1
<link rel="import" href="share-buttons.html">

然后,就可以在网页中使用``了。

XHTML

<article> <h1>Title</h1> <share-buttons/> ... ... </article>

1
2
3
4
5
<article>
  <h1>Title</h1>
  <share-buttons/>
  ... ...
</article>

HTML imports 的更多用法可以参考教程(1,2)。目前只有 Chrome 浏览器支持这个语法。

Custom Elements

三、Custom Elements 标准

HTML5 标准规定了自定义元素是合法的。然后,W3C 就为自定义元素制定了一个单独的 Custom Elements 标准。

它与其他三个标准放在一起—- HTML Imports,HTML Template、Shadow DOM—-统称为 Web Components 规范。目前,这个规范只有 Chrome 浏览器支持。

威尼斯澳门在线 5

Custom Elements 标准对自定义元素的名字做了限制。

“自定义元素的名字必须包含一个破折号(-)所以都是正确的名字,而和``是不正确的。这样的限制使得 HTML 解析器可以分辨那些是标准元素,哪些是自定义元素。”

威尼斯澳门在线 6

注意,一旦名字之中使用了破折号,自定义元素就不是HTMLUnknownElement的实例了。

JavaScript

var xTabs = document.createElement('x-tabs'); xTabs instanceof HTMLUnknownElement // false xTabs instanceof HTMLElement // true

1
2
3
4
var xTabs = document.createElement('x-tabs');
 
xTabs instanceof HTMLUnknownElement // false
xTabs instanceof HTMLElement // true

Custom Elements 标准规定了,自定义元素的定义可以使用 ES6 的class语法。

JavaScript

// 定义一个 class MyElement extends HTMLElement {...} window.customElements.define('my-element', MyElement);

1
2
3
// 定义一个
class MyElement extends HTMLElement {...}
window.customElements.define('my-element', MyElement);

上面代码中,原生的window.customElements对象的define方法用来定义 Custom Element。该方法接受两个参数,第一个参数是自定义元素的名字,第二个参数是一个 ES6 的class

这个class使用getset方法定义 Custom Element 的某个属性。

JavaScript

class MyElement extends HTMLElement { get content() { return this.getAttribute('content'); } set content(val) { this.setAttribute('content', val); } }

1
2
3
4
5
6
7
8
9
class MyElement extends HTMLElement {
  get content() {
    return this.getAttribute('content');
  }
 
  set content(val) {
    this.setAttribute('content', val);
  }
}

有了这个定义,网页之中就可以插入``了。

JavaScript

<my-element content="Custom Element"> Hello </my-element>

1
2
3
<my-element content="Custom Element">
  Hello
</my-element>

处理脚本如下。

JavaScript

function customTag(tagName, fn){ Array .from(document.getElementsByTagName(tagName)) .forEach(fn); } function myElementHandler(element) { element.textConent = element.content; } customTag('my-element', myElementHandler);

1
2
3
4
5
6
7
8
9
10
11
function customTag(tagName, fn){
  Array
    .from(document.getElementsByTagName(tagName))
    .forEach(fn);
}
 
function myElementHandler(element) {
  element.textConent = element.content;
}
 
customTag('my-element', myElementHandler);

运行结果如下。

威尼斯澳门在线 7

ES6 Class 的一个好处是,可以很容易地写出继承类。

JavaScript

class MyNewElement extends MyElement { // ... } customElements.define('my-new-element', MyNewElement);

1
2
3
4
5
class MyNewElement extends MyElement {
  // ...
}
 
customElements.define('my-new-element', MyNewElement);

今天的教程就到这里,更多用法请参考谷歌的官方教程。

概述

Custom Elements 顾名思义,是提供一种方式让开发者可以自定义 HTML 元素,包括特定的组成,样式和行为。支持 Web Components 标准的浏览器会提供一系列 API 给开发者用于创建自定义的元素,或者扩展现有元素。

这一项标准的草案还处于不稳定的状态,时有更新,API 还会有所变化,下边的笔记以 Cutsom Elements 2016.02.26 这个版本为准,因为在最新的 chrome 浏览器已经是可以工作的了,这样可以使用 demo 来做尝试,最后我会再简单写一下最新文档和这个的区别。

四、参考链接

  • John Negoita, Extending HTML by Creating Custom Tags
  • StackOverflow, Are custom elements valid HTML5?
  • Eric Bidelman, Custom Elements v1: Reusable Web Components

 

1 赞 1 收藏 评论

威尼斯澳门在线 8

registerElement

首先,我们可以尝试在 chrome 控制台输入 HTMLInputElement,可以看到是有这么一个东西的,这个理解为 input DOM 元素实例化时的构造函数,基础的是 HTMLElement

Web Components 标准提出提供这么一个接口:

JavaScript

威尼斯澳门在线 ,document.registerElement('x-foo', { prototype: Object.create(HTMLElement.prototype, { createdCallback: { value: function() { ... } }, ... }) })

1
2
3
4
5
6
7
8
document.registerElement('x-foo', {
  prototype: Object.create(HTMLElement.prototype, {
    createdCallback: {      
      value: function() { ... }
    },
    ...
  })
})

你可以使用 document.registerElement 来注册一个标签,标准中为了提供 namesapce 的支持,防止冲突,规定标签类型(也可以理解为名字)需要使用 - 连接。同时,不能是以下这一些:

  • annotation-xml
  • color-profile
  • font-face
  • font-face-src
  • font-face-uri
  • font-face-format
  • font-face-name
  • missing-glyph

第二个参数是标签相关的配置,主要是提供一个 prototype,这个原型对象是以 HTMLElement 等的原型为基础创建的对象。然后你便可以在 HTML 中去使用自定义的标签。如:

XHTML

<div> <x-foo></x-foo> </div>

1
2
3
<div>
  <x-foo></x-foo>
</div>

是不是嗅到了 React 的味道?好吧,React 说它自己主要不是做这个事情的。

生命周期和回调

在这个 API 的基础上,Web Components 标准提供了一系列控制自定义元素的方法。我们来一一看下:

一个自定义元素会经历以下这些生命周期:

  • 注册前创建
  • 注册自定义元素定义
  • 在注册后创建元素实例
  • 元素插入到 document 中
  • 元素从 document 中移除
  • 元素的属性变化时

这个是很重要的内容,开发者可以在注册新的自定义元素时指定对应的生命周期回调来为自定义元素添加各种自定义的行为,这些生命周期回调包括了:

  • createdCallback
    自定义元素注册后,在实例化之后会调用,通常多用于做元素的初始化,如插入子元素,绑定事件等。
  • attachedCallback
    元素插入到 document 时触发。
  • detachedCallback
    元素从 document 中移除时触发,可能会用于做类似 destroy 之类的事情。
  • attributeChangedCallback
    元素属性变化时触发,可以用于从外到内的通信。外部通过修改元素的属性来让内部获取相关的数据并且执行对应的操作。

这个回调在不同情况下有对应不同的参数:

  • 设置属性时,参数列表是:属性名称,null,值,命名空间
  • 修改属性时,参数列表是:属性名称,旧值,新值,命名空间
  • 删除属性时,参数列表是:属性名称,旧值,null,命名空间

好了,就上边了解到的基础上,假设我们要创建一个自定义的 button-hello 按钮,点击时会 alert('hello world'),代码如下:

JavaScript

document.registerElement('button-hello', { prototype: Object.create(HTMLButtonElement.prototype, { createdCallback: { value: function createdCallback() { this.innerHTML = '<button>hello world</button>' this.addEventListener('click', () => { alert('hello world') }) } } }) })

1
2
3
4
5
6
7
8
9
10
11
12
document.registerElement('button-hello', {
  prototype: Object.create(HTMLButtonElement.prototype, {
    createdCallback: {
      value: function createdCallback() {
        this.innerHTML = '<button>hello world</button>'
        this.addEventListener('click', () => {
          alert('hello world')
        })
      }
    }
  })
})

要留意上述代码执行之后才能使用 <button-hello></button-hello>

扩展原有元素

其实,如果我们需要一个按钮,完全不需要重新自定义一个元素,Web Components 标准提供了一种扩展现有标签的方式,把上边的代码调整一下:

JavaScript

document.registerElement('button-hello', { prototype: Object.create(HTMLButtonElement.prototype, { createdCallback: { value: function createdCallback() { this.addEventListener('click', () => { alert('hello world') }) } } }), extends: 'button' })

1
2
3
4
5
6
7
8
9
10
11
12
document.registerElement('button-hello', {
  prototype: Object.create(HTMLButtonElement.prototype, {
    createdCallback: {
      value: function createdCallback() {
        this.addEventListener('click', () => {
          alert('hello world')
        })
      }
    }
  }),
  extends: 'button'
})

然后在 HTML 中要这么使用:

XHTML

<button is="button-hello">hello world</button>

1
<button is="button-hello">hello world</button>

使用 is 属性来声明一个扩展的类型,看起来也蛮酷的。生命周期和自定义元素标签的保持一致。

当我们需要多个标签组合成新的元素时,我们可以使用自定义的元素标签,但是如果只是需要在原有的 HTML 标签上进行扩展的话,使用 is 的这种元素扩展的方式就好。

原有的 createElementcreateElementNS,在 Web Components 标准中也扩展成为支持元素扩展,例如要创建一个 button-hello

JavaScript

const hello = document.createElement('button', 'button-hello')

1
const hello = document.createElement('button', 'button-hello')

标准文档中还有很多细节上的内容,例如接口的参数说明和要求,回调队列的实现要求等,这些更多是对于实现这个标准的浏览器开发者的要求,这里不做详细描述了,内容很多,有兴趣的自行查阅:Cutsom Elements 2016.02.26。

和最新版的区别

前边我提到说文档的更新变化很快,截止至我写这个文章的时候,最新的文档是这个:Custom Elements 2016.07.21。

细节不做描述了,讲讲我看到的最大变化,就是向 ES6 靠拢。大致有下边三点:

  • 从原本的扩展 prototype 来定义元素调整为建议使用 class extends 的方式
  • 注册自定义元素接口调整,更加方便使用,传入 type 和 class 即可
  • 生命周期回调调整,createdCallback 直接用 class 的 constructor

前两个点,我们直接看下代码,原本的代码按照新的标准,应该调整为:

JavaScript

class ButtonHelloElement extends HTMLButtonElement { constructor() { super() this.addEventListener('click', () => { alert('hello world') }) } } customElements.define('button-hello', ButtonHelloElement, { extends: 'button' })

1
2
3
4
5
6
7
8
9
10
11
class ButtonHelloElement extends HTMLButtonElement {
  constructor() {
    super()
 
    this.addEventListener('click', () => {
      alert('hello world')
    })
  }
}
 
customElements.define('button-hello', ButtonHelloElement, { extends: 'button' })

从代码上看会感觉更加 OO,编写上也比原本要显得方便一些,原本的生命周期回调是调整为新的:

  • constructor in class 作用相当于原本的 createdCallback
  • connectedCallback 作用相当于 attachedCallback
  • disconnectedCallback 作用相当于 detachedCallback
  • adoptedCallback 使用 document.adoptNode(node) 时触发
  • attributeChangedCallback 和原本保持一致

connect 事件和插入元素到 document 有些许区别,主要就是插入元素到 document 时,元素状态会变成 connected,这时会触发 connectedCallback,disconnect 亦是如此。

HTML Imports

概述

HTML Imports 是一种在 HTMLs 中引用以及复用其他的 HTML 文档的方式。这个 Import 很漂亮,可以简单理解为我们常见的模板中的include 之类的作用。

我们最常见的引入一个 css 文件的方式是:

XHTML

<link rel="stylesheet" href="/css/master.css">

1
<link rel="stylesheet" href="/css/master.css">

Web Components 现在提供多了一个这个:

XHTML

<link rel="import" href="/components/header.html">

1
<link rel="import" href="/components/header.html">

HTMLLinkElement

原本的 link 标签在添加了 HTML Import 之后,多了一个只读的 import 属性,当出现下边两种情况时,这个属性为 null

  • link 不是用来 import 一个 HTML 的。
  • link 元素不在 document 中。

否则,这个属性会返回一个表示引入的 HTML 文件的文档对象,类似于 document。比如说,在上边的代码基础上,可以这样做:

JavaScript

const link = document.querySelector('link[rel=import]') const header = link.import; const pulse = header.querySelector('div.logo');

1
2
3
4
const link = document.querySelector('link[rel=import]')
const header = link.import;
 
const pulse = header.querySelector('div.logo');

阻塞式

我们要知道的是,默认的 link 加载是阻塞式的,除非你给他添加一个 async 标识。

阻塞式从某种程度上讲是有必要的,当你 improt 的是一个完整的自定义组件并且需要在主 HTML 中用标签直接使用时,非阻塞的就会出现错误了,因为标签还没有被注册。

本文由澳门在线威尼斯官方发布于威尼斯澳门在线,转载请注明出处:是个什么样的东西,自定义元素教程

关键词:

上一篇:目前无法实现的5件事,现代播放器原理

下一篇:没有了