在Web组件中,要注册元素,只需键入:
var XFoo = document.registerElement('x-foo', {
prototype: Object.create(HTMLElement.prototype)
});
Run Code Online (Sandbox Code Playgroud)
要创建元素,您可以执行以下操作之一:
<x-foo></x-foo>
var xFoo = new XFoo();
document.body.appendChild(xFoo);
var xFoo = document.createElement( 'x-foo')
document.body.appendChild(xFoo);
Run Code Online (Sandbox Code Playgroud)
这一切都很好,花花公子.当您谈论扩展现有元素时,问题就开始了.
var XFooButton = document.registerElement('x-foo-button', {
prototype: Object.create(HTMLButtonElement.prototype),
extends: 'button'
});
Run Code Online (Sandbox Code Playgroud)
问题1:为什么重复?在这里,'button'应该足够了(特别是因为它很容易计算元素的原型Object.getPrototypeOf(document.createElement(tag));
问题2:内部如何使用该信息?例如,如果您拥有prototype: Object.create(HTMLFormElement.prototype和extends: 'button'(后面的内容extends与原型传递不匹配)会发生什么
要创建一个,您可以执行以下操作之一:
<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);
Run Code Online (Sandbox Code Playgroud)
问题3:因为很明显x-foo-button扩展了button,为什么我们在使用时必须指定它们document.createElement()?我怀疑那是因为document.createElement()只是创建一个带语法的标签<button is="x-foo-button"></button>,这让我想到了下一个问题:
问题4 …
我是网络开发的新手,最近我看到很多关于Custom Elements v1的辩论和讨论.它们允许您使用自己的自定义行为定义自己的元素,如果使用Shadow DOM,则使用范围样式.
当我在这个网站上了解它时,我不理解"自定义元素反应"下的表格.任何人都可以解释使用"构造函数"和"connectedCallback"以及术语"创建或升级"和"插入DOM"之间的区别吗?
有关额外信息,我的自定义元素的定义位于单独的文件中,它使用shadow DOM.我使用HTML Import将元素的定义导入主文档.
class A extends HTMLElement {
constructor() {
super()
return new Proxy(this, {})
}
}
window.customElements.define('a-element', A)Run Code Online (Sandbox Code Playgroud)
<a-element></a-element>Run Code Online (Sandbox Code Playgroud)
我如何代理自定义元素?
当我尝试它:
Uncaught InvalidStateError: custom element constructors must call super() first and must not return a different object.
tl;博士:
aria-labelledby在这种情况下,屏幕阅读器会正确处理吗?例如,考虑这个自定义元素:
(function () {
let template = document.createElement('template')
template.innerHTML = `
<svg viewBox="0 0 206 74"
fill="none"
xmlns="http://www.w3.org/2000/svg"
role="img"
aria-labelledby="logo-title">
<title id="logo-title"><slot>Logo of Some Company.</slot></title>
<path d="..." fill="..."/>
</svg>
`
class Logo extends HTMLElement {
constructor () {
super()
let shadowRoot = this.attachShadow({mode: 'open'})
shadowRoot.appendChild(template.content.cloneNode(true))
}
}
customElements.define('company-logo', Logo)
})()
Run Code Online (Sandbox Code Playgroud)
这样做是否有效:
<company-logo>
Title One.
</company-logo>
<company-logo>
Some other title.
</company-logo>
Run Code Online (Sandbox Code Playgroud)
这会是一个有效的 DOM,即使两者<title>共享相同的 ID?屏幕阅读器会为第一个徽标读“标题一”,为第二个徽标读“其他标题”吗?
考虑以下Polymer自定义元素:
<dom-module id="test-element">
<template>
<input type="text" value="{{value}}">
<button>Reset</button>
</template>
<script>
Polymer({
is: 'test-element',
properties: {
'value': {
type: String,
reflectToAttribute: true,
notify: true,
value: null
}
}
});
</script>
</dom-module>
Run Code Online (Sandbox Code Playgroud)
我在index.html中使用这个自定义元素,如下所示:
<html>
<head>
<script type="text/javascript" src="bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="test-element.html">
<title>Test App</title>
</head>
<body>
<test-element value="test"></test-element>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
我相信我已经将该value属性声明为双向绑定(notify: true); 然而,当我点击输入并键入一些文本(例如"foo")时,它不会反映在模型中(即调用document.querySelector('test-element').value返回我在index.html中设置的值"test").有趣的是,value输入的属性正确更改,但我的test-element的value属性没有.我错过了什么?
我还应该注意一个document.querySelector('test-element').setAttribute('value', 'bar')正常工作的电话.
在没有任何框架的情况下使用Web Components,实现自定义事件的正确方法是什么?例如,假设我有一个x-pop-out具有自定义事件的自定义元素,pop我希望以下所有内容都能正常工作:
<x-pop-out onpop="someGlobal.doSomething()"/>
var el = document.getElementsByTagName('x-pop-out')[0];
el.onpop = ()=> someGlobal.doSomething();
//or
el.addEventListener('pop', ()=> someGlobal.doSomething());
Run Code Online (Sandbox Code Playgroud)
最后一个我知道该怎么做,但是我是否需要为每个属性和一个 getter/setter 自定义实现?另外,eval()从属性执行字符串的适当方法是什么?
这段代码给出了“非法构造函数”错误,有人能告诉我为什么吗?
class MyCustomElement extends HTMLElement {
constructor(){
super();
// Other things
}
}
const myFunc = () => {
const instance = new MyCustomElement();
console.log(instance);
}
myFunc();Run Code Online (Sandbox Code Playgroud)
我正在使用本机实现创建一个Web组件,在它的html模板中有指向图像的链接.但是,这些链接仅在绝对或相对于主文档时才起作用,这意味着该组件不可重用或可移植.而且,这非常违反直觉.
目前,我将data-url_prefix属性添加到需要使用图像的所有元素.然后,在为自定义元素创建阴影根时,我将{{URL_PREFIX}}替换为该参数的值.
我的解决方案似乎很糟糕.如果你建议更好的东西,我会很高兴,谢谢.
我在http://webcomponents.org/polyfills/html-imports/页面上找到了一个有趣的引用:
POLYFILL笔记
在导入的文档中,HTML中的href和src属性以及CSS文件中的url属性是相对于导入文档的位置而不是主文档的位置.
为什么polifill会使用与本机实现不同的逻辑?
Web组件理想情况下应该封装它们的所有依赖项,但是如果Web组件需要图像,它应该知道该图像的绝对URL,这不允许在文件结构中简单地移动组件.
比方说,例如我有以下结构:
如果我将其更改为以下内容:
我将被要求在这些文件中的某处更改指向icon.png的指针我的问题是如何避免它,或以优雅的方式解决它.另外,为什么实际的原生实现与polyfill冲突?
因此,在我正在创建的使用自定义元素的库中,您显然需要在CustomElementsRegistry实例化之前定义该类.
截至目前,这是由装饰者解决:
class Component extends HTMLElement {
static register (componentName) {
return component => {
window.customElements.define(componentName, component);
return component;
}
}
}
@Component.register('my-element')
class MyElement extends Component { }
document.body.appendChild(new MyElement());
Run Code Online (Sandbox Code Playgroud)
这个工程,不过,我想在这个类(所以笔者并没有给装饰添加到他们写的每一个组成部分)的实例自动注册自定义元素.这可以通过一个完成Proxy.
但问题是,当我尝试在构造函数上使用Proxy,并尝试返回目标的实例时,我仍然会得到Illegal Constructor,就好像该元素从未在注册表中定义一样.
这显然与我在代理中实例化类的方式有关,但我不确定如何做到这一点.我的代码如下:
请在最新的Chrome中运行:
class Component extends HTMLElement {
static get componentName () {
return this.name.replace(/[A-Z]/g, char => `-${ char.toLowerCase() }`).substring(1);
}
}
const ProxiedComponent = new Proxy(Component, {
construct (target, args, extender) {
const { componentName } = extender;
if …Run Code Online (Sandbox Code Playgroud)我正在尝试在打字稿中实现网络自定义元素。我发现自定义元素的生命周期回调如下
connectedCallback()adoptedCallback()attributeChangedCallback()这些回调有打字稿接口吗?我可以使用适当的签名编写这些方法,但我更愿意使用现有的定义。
custom-element ×10
javascript ×8
html ×4
polymer ×2
shadow-dom ×2
es6-class ×1
es6-proxy ×1
typescript ×1