在网络组件中,要注册一个元素,您只需键入:
var XFoo = document.registerElement('x-foo', {
prototype: Object.create(HTMLElement.prototype)
});
要创建一个元素,您可以执行以下操作之一:
<x-foo></x-foo>
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 之后的内容与传递的原型(prototype)不匹配)
要创建一个,您可以执行以下操作之一:
<button is="x-foo-button"></button>
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()只需创建一个语法为 <button is="x-foo-button"></button> 的标签,这让我想到下一个问题:
问题 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) 第一个语法需要 <button is="x-foo-button"></button>在文档中创建实例 2) 第二种语法可以用于任何元素,而不仅仅是自定义元素的扩展?
最佳答案
答案 1
明显的重复是因为您的示例非常简单。在真实的虚拟生活中,你会提供一个不同的原型(prototype)给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 代码:
<button is="x-foo-button" id="Hello" value="World"> Hello </button>
点击它会在弹出窗口中显示“Hello World”。
答案 2
extends: 'button'是一个语义指示,告诉浏览器所提供的新原型(prototype)实现了 HTMLButtonElement界面。这就是为什么从继承自 HTMLButtonElement 的对象开始更容易的原因.相反,您可以从 HTMLFormElement 开始原型(prototype),但您必须重新实现 HTMLButtonElement 的所有属性和方法。界面。
否则,元素行为将不正确。在上面的示例中,如果您将一行替换为:
var newProto = Object.create( HTMLFormElement.prototype )
...点击它会失败,因为属性 value未在 <form> 中实现元素。
属性(property)id总是正确的,因为它由 HTMLElement 提供接口(interface),由每个元素(包括 <form> )实现。
请注意,您可以添加缺少的属性,并将它们链接到它们在 attributeChangedCallback 中的属性方法。
答案 3
你是对的。这保持了与将忽略第二个参数的旧浏览器的向后兼容性,仍然能够创建普通元素(在您的示例中为标准 <button>)。
答案 4 自定义元素范例背后有两个不同的概念:
两者都是用相同的方法定义的registerElement . extends/is选项允许您选择其中之一。
is语法仅适用于类型扩展,因此始终与 extends 相关联选项。
使用类型扩展,您可以保留所扩展元素的所有语义: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 <button is=...>
}
catch (e) {
output += "a generic element"
}
alert(output)
}
}
//Type Extension
var newProto = Object.create(HTMLButtonElement.prototype)
newProto.createdCallback = callback
var XFooButtonExt = document.registerElement('x-foo-button', {
prototype: newProto,
extends: 'button'
})
//Custom Tag
var newProto2 = Object.create(HTMLButtonElement.prototype)
newProto2.createdCallback = callback
var XFooButtonCust = document.registerElement('x-foo-button-2', {
prototype: newProto2,
})<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Custom Elements</title>
</head>
<body>
<h3>Type Extension</h3>
<button is="x-foo-button" id="I'm" name="a button">Type Extension</button>
<h3>Custom Tag</h3>
<x-foo-button-2 id="I'm" name="a button">Custom Tag</x-foo-button-2>
</body>
</html>
关于javascript - 在 Web 组件中扩展元素时, "is"语法有何意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34055503/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub