在Web组件中,要注册元素,只需键入:
var XFoo = document.registerElement('x-foo', { prototype: Object.create(HTMLElement.prototype) });
要创建元素,您可以执行以下操作之一:
var xFoo = new XFoo(); document.body.appendChild(xFoo); var xFoo = document.createElement( 'x-foo') document.body.appendChild(xFoo);
这一切都很好,花花公子.当您谈论扩展现有元素时,问题就开始了.
var XFooButton = document.registerElement('x-foo-button', { prototype: Object.create(HTMLButtonElement.prototype), extends: 'button' });
问题1:为什么重复?在这里,'button'
应该足够了(特别是因为它很容易计算元素的原型Object.getPrototypeOf(document.createElement(tag));
问题2:内部如何使用该信息?例如,如果您拥有prototype: Object.create(HTMLFormElement.prototype
和extends: 'button'
(后面的内容extends
与原型传递不匹配)会发生什么
要创建一个,您可以执行以下操作之一:
var xFooButton = new XFooButton(); document.body.appendChild(xFoo); var xFooButton = document.createElement('button', 'x-foo-button'); document.body.appendChild(xFooButton);
问题3:因为很明显x-foo-button
扩展了button
,为什么我们在使用时必须指定它们document.createElement()
?我怀疑那是因为document.createElement()
只是创建一个带语法的标签,这让我想到了下一个问题:
问题4:is
语法的重点是什么?这样做的实际区别是什么:
var XFooButton = document.registerElement('x-foo-button', { prototype: Object.create(HTMLButtonElement.prototype), extends: 'button' });
还有这个:
var XFooButton = document.registerElement('x-foo-button', { prototype: Object.create(HTMLButtonElement.prototype), });
除了1)第一种语法需要在文档中创建一个实例2)第二种语法可以用于任何元素,而不仅仅是自定义元素的扩展?
答案1
明显的重复是因为你的例子非常简单.在真实的虚拟生活中,你会提供一个不同的原型registerElement
.
使用自定义按钮的示例,单击时将显示弹出窗口:
//Custom method function callback () { console.log( this + " {created}" ) this.onclick = function ( event ) { alert( this.id + " " + this.value ) } } //Type Extension var newProto = Object.create( HTMLButtonElement.prototype ) newProto.createdCallback = callback var XFooButtonExt = document.registerElement( 'x-foo-button', { prototype: newProto, extends: 'button' } )
newProto
比不同HTMLButtonElement
的prototype
.
使用以下HTML代码:
单击它将在弹出窗口中显示"Hello World".
答案2
这extends: 'button'
是一个语义指示,告诉浏览器提供的新原型实现了HTMLButtonElement
接口.这就是为什么从一个继承的对象开始更容易的原因HTMLButtonElement
.相反,您可以从HTMLFormElement
原型开始,但您必须重新实现HTMLButtonElement
接口的所有属性和方法.
如果不是,则元素行为将不正确.在上面的示例中,如果您将行替换为:
var newProto = Object.create( HTMLFormElement.prototype )
...单击它将失败,因为该属性value
未在元素中实现.
该属性id
始终是正确的,因为它由HTMLElement
接口提供,由每个元素(包括)实现.
请注意,您可以添加缺少的属性,并将它们链接到attributeChangedCallback
方法中的属性.
答案3
你是对的.这保持了与旧浏览器的向后兼容性,这些浏览器将忽略第二个参数,仍然能够创建普通元素(在您的示例中为标准).
答案4 自定义元素范例 背后有两个不同的概念:
如果要扩展标准HTML元素,请键入Extensions(自定义内置元素).
自定义标记(自治自定义元素),如果要使用新名称定义自定义元素.
两者都用相同的方法定义registerElement
.在extends
/ is
选项允许你选择其中之一.
该is
语法仅适用于Type Extensions,因此始终与该extends
选项相关联.
使用Type Extensions,您可以保留所扩展元素的所有语义:CSS样式,内置行为(接口),可访问性功能.向后兼容性是此语法的另一个好处.
使用自定义标记,您将失去语义,并且您的自定义元素只能实现HTMLElement
接口,没有内置样式或行为.
更新:下一个示例(适用于Chrome和Opera)说明了类型扩展和自定义标记之间的区别.
//Method
function callback() {
this.textContent = this //Get the HTML semantics
this.onclick = function(event) {
try {
var output = this.id + " "
output += this.name //works only with
Custom Elements
Type Extension
Custom Tag
Custom Tag