有没有办法用CSS选择所有自定义元素?我希望默认情况下使所有自定义元素块元素(大多数浏览器默认情况下使它们内联),然后根据需要覆盖它.
我的规则看起来像这样:
*::custom {
display: block;
}
Run Code Online (Sandbox Code Playgroud)
所有自定义元素在标准中都有破折号,因此我可以创建一个利用它的规则,但在许多/大多数当前浏览器上它会更慢,因为它需要使用正则表达式.如果有内置选择器,这可能会更快.
我正在嵌套自定义元素.我想让我的父自定义元素使用其子自定义元素原型中的方法和属性.例如
<script>
var ChildElement = Object.create(HTMLElement.prototype);
ChildElement.getName = function () {
return "Bob";
}
document.registerElement("child-element", {
prototype: ChildElement
});
var ParentElement = Object.create(HTMLElement.prototype);
ParentElement.createdCallback = function () {
var self = this;
setTimeout(function () {
// This logs 'Bob', correctly
console.log(self.childNodes[0].getName());
}, 0);
// This explodes - getName is not defined.
console.log(self.childNodes[0].getName());
};
document.registerElement("parent-element", {
prototype: ParentElement
});
</script>
<parent-element><child-element></child-element></parent-element>
Run Code Online (Sandbox Code Playgroud)
如内联所述,父级无法读取子元素原型上定义的任何内容.它可以,如果它立即触发一个setTimeout; 它只需要等到这个元素的子节点也被设置好了.
看起来这是因为元素创建过程中的回调顺序,我认为是这样的:
在这一点上,createdCallback触发是有道理的,但据我所知,当你所有的孩子都被创建时,根本没有可用的回调.我认为这意味着不可能在使用子元素原型的创建上做任何事情,而不使用setTimeout等待整个页面完成渲染.
是否有任何可以从父级监听的回调或事件,只有在设置了所有子节点的原型后才会触发?是否有一种不同的方法可以让你使用这样的结构?除了触发setTimeout之外,还有什么可以做的吗?
我认为自定义元素的设计允许使用其他元素内容进行参数化,并且在该内容中有效地不支持自定义元素是非常令人惊讶的.
可以说,这可以被认为是在创建custom-tag时访问子节点时未定义的Prototype的副本.然而,这个问题的措辞很差,破坏的例子,唯一的答案似乎实际上是一个实现错误,而不是解决方案(或者至少,它不再是当前的浏览器行为)
我有一堆以'food-cta-'开头的自定义元素.我正在寻找JavaScript/jQuery中的一种方法来选择这些元素.这类似于我可以$('*[class^="food-cta-"]')用来选择所有开头的类food-cta-.是否可以搜索以'food-cta-'开头的元素?
请注意,我将在页面上注入此搜索,因此我无法访问Angular.
自定义元素的示例:
<food-cta-download><food-cta-external><food-cta-internal>编辑:我看的代码看起来像:
<food-cta-download type="primary" description="Download Recipe">
<img src="">
<h2></h2>
<p></p>
</food-cta-download>
Run Code Online (Sandbox Code Playgroud)
该应用程序使用AngularJS创建自定义元素,我相信这些元素称为指令.
尝试webcomponents但是我得到了一个错误.
标记很简单,应该可行.2个文件,都是html文件.
错误标记在<script>控制台中的标记上.
谢谢你的帮助.
PS.我正在运行Google Chrome测试版以使customElements正常运行.
KM-button.html
<script>
class KmButton extends HTMLButtonElement {
constructor() {
super();
}
}
customElements.define('km-button', KmButton, {extends: 'button'});
</script>
Run Code Online (Sandbox Code Playgroud)
的index.html
<!DOCTYPE html>
<html>
<head>
<!-- import webcomponents -->
<link rel="import" href="./components/km-button.html">
</head>
<body>
<km-button>hej</km-button>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
错误
km-button.html:1 Uncaught TypeError: Illegal constructor(…)KmButton @ km-button.html:7
Run Code Online (Sandbox Code Playgroud) 我已经将Mozzila示例https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements#Observed_attributes中的代码复制并粘贴到 我的计算机上的文件中,当我运行它时,我从每次调用this.getAttribute.我看到它在上面的链接上工作但是当我运行我复制的项目时,它是null,在我编写的另一个项目中发生同样的事情,基于这个例子:
HTML文件:
If nothing appeared below, then your browser does not support Custom Elements yet.
<x-product data-name="Ruby" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/ruby.png" data-url="http://example.com/1"></x-product>
<x-product data-name="JavaScript" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/javascript.png" data-url="http://example.com/2"></x-product>
<x-product data-name="Python" data-img="https://s3-us-west-2.amazonaws.com/s.cdpn.io/4621/python.png" data-url="http://example.com/3"></x-product>
Run Code Online (Sandbox Code Playgroud)
JS档案:
// Create a class for the element
class XProduct extends HTMLElement {
constructor() {
// Always call super first in constructor
super();
// Create a shadow root
var shadow = this.attachShadow({mode: 'open'});
// Create a standard img element and set it's attributes.
var img = document.createElement('img');
img.alt = this.getAttribute('data-name'); …Run Code Online (Sandbox Code Playgroud) 我将 Vue 的单文件组件规范 ( *.vue) 用于我的应用程序中的自定义组件。与rollup和一起rollup-plugin-vue,我观察到 DOM 中的输出,对于我编写的自定义组件,由等效的 html 元素组成。
例如:
component-a.vue
<template>
<span>Hello World</span>
</template>
<script>
export default { name: 'component-a' };
</script>
Run Code Online (Sandbox Code Playgroud)
component-b.vue
<template>
<component-a></component-a>
</template>
<script>
import ComponentA from './path/to/component-a.vue';
export default { name: 'component-b', components: { ComponentA } };
</script>
Run Code Online (Sandbox Code Playgroud)
上面的例子,如果component-a被添加到 Vue 挂载组件中,将会渲染到DOM 中两个组件的模板内容的总和,在这种情况下它只是一个span元素:
<span>Hello World<span>
Run Code Online (Sandbox Code Playgroud)
是否可以像下面的代码片段那样在 DOM 中实现渲染输出,这样自定义元素的模板在 DOM 中由保留其标签名称的标签表示?
<component-b>
<component-a>
<span>Hello World</span>
</component-a>
</component-b>
Run Code Online (Sandbox Code Playgroud) 注册后是否可以修改自定义元素/Web 组件类?这不是我通常(或永远)想要在生产代码中做的事情,但是在原型设计或实现用于开发的代码修补工具时,它会很有用。到目前为止,这是我尝试过但未成功的方法:
document.body.appendChild(document.createElement('foo-bar')) // empty element
class FooBar extends HTMLElement {
connectedCallback () {
this.textContent = 'foo bar'
}
}
customElements.define('foo-bar', FooBar) // element shows "foo bar"
FooBar.protoype.connectedCallback = function () {
this.textContent = 'foo bar 2'
}
document.body.appendChild(document.createElement('foo-bar')) // element shows "foo bar", not "foo bar 2"
customElements.get('foo-bar').protoype.connectedCallback = function () {
this.textContent = 'foo bar 2'
}
document.body.appendChild(document.createElement('foo-bar')) // element shows "foo bar", not "foo bar 2"
class FooBar2 extends HTMLElement {
connectedCallback () {
this.textContent = 'foo …Run Code Online (Sandbox Code Playgroud) 我创建了一个如下所示的 Angular Web 组件
@Component({
selector: 'dlx-slider',
templateUrl: './slider.component.html',
styleUrls: ['./slider.component.scss'],
encapsulation: ViewEncapsulation.Native,
})
export class SliderComponent implements OnInit {
open() {
console.log('open');
}
close() {
console.log('close');
}
}
Run Code Online (Sandbox Code Playgroud)
在我的应用程序模块中
export class AppModule {
constructor(private injector: Injector) {
}
ngDoBootstrap() {
this.defineElement(SliderComponent, 'dlx-slider');
}
private defineElement(component: any, elementName: string) {
const el = createCustomElement(component, { injector: this.injector });
customElements.define(elementName, el);
}
}
Run Code Online (Sandbox Code Playgroud)
一切正常,我已经将它嵌入到一个简单的 HTML 页面中,如下所示
<head>
<meta charset="utf-8">
<title>TMIBot</title>
<base href="/">
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0, user-scalable=no">
<title>Test Angular Elements</title> …Run Code Online (Sandbox Code Playgroud) 我的问题中粘贴的声明是从https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#Using_the_lifecycle_callbacks复制的。
作为一名没有 WebComponent 经验的开发人员,我试图了解迄今为止推荐的所有经验法则和最佳实践。
继续阅读它说“...使用 Node.isConnected 来确保”。它的含义很明显:检查它是否仍然连接,但至少对我来说,尚不清楚我应该采取什么措施来解决它,或者在某些情况下我应该期待什么。
我的情况是我正在创建一个 Web 组件来侦听 SSE(服务器发送事件)。这对于 alife 仪表板和其他几个场景非常有用。SSE事件在从Kafka Stream消费后基本上将由NodeJs或Spring Webflux响应。
到目前为止,我所做的所有简单示例都没有遇到任何元素在连接回调期间不再连接的问题。
此外,我没有阅读最佳实践中关于“不再连接的元素”的任何建议。
我读了一些精彩的讨论:
从那里我了解到我始终可以信任这个生命周期构造函数 -->connectedCallback -->disconnectedCallback。
和
当所有子自定义元素已连接时如何拥有“connectedCallback”
基本上我了解到没有一个特定的方法“在所有孩子都升级后调用”
这两个问题都接近我的问题,但它没有回答我:应该注意哪些挑战或风险,或者如何解决“一旦元素不再连接,可能会调用connectedCallback”的可能性?在我上述的情况下,我是否缺少任何治疗?我是否应该创建一些观察者,当该元素不再可用时触发,以重新创建事件源对象并再次向此类事件源对象添加侦听器?
我粘贴了下面的代码进行说明,完整的 Web 组件示例可以从https://github.com/jimisdrpc/simplest-webcomponet克隆,其后端可以从https://github.com/jimisdrpc/simplest-kafkaconsumer克隆。
const template = document.createElement('template');
template.innerHTML = `<input id="inputKafka"/> `;
class InputKafka extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.attachShadow({mode: 'open'})
this.shadowRoot.appendChild(template.content.cloneNode(true))
const inputKafka = this.shadowRoot.getElementById('inputKafka');
var source = new EventSource('http://localhost:5000/kafka_sse');
source.addEventListener('sendMsgFromKafka', function(e) {
console.log('fromKafka');
inputKafka.value = e.data;
}, false);
}
attributeChangedCallback(name, …Run Code Online (Sandbox Code Playgroud) html javascript web-component custom-element native-web-component
我正在构建一个仅使用本机、普通 JS 功能(ES6、Web 组件、导入模块)的网站。
我想包含一个 polyfill 来让 Safari 支持扩展 HTML 元素 ( class MyLink extends HTMLAnchorElement)。理想情况下,我想通过importmain.js 文件中包含它,而不是作为<script>index.html 中的标签。
我首先尝试了官方的Custom Elements V1 polyfill,包括通过脚本标签 ( <script src="https://unpkg.com/@webcomponents/custom-elements"></script>) 和import(import "https://cdn.skypack.dev/@webcomponents/custom-elements"; )。两种方式都没有错误,但我没有看到在 Safari 上扩展内置元素的支持。
我尝试了一个不同的polyfill,它明确提到了可定制的内置元素,在这种情况下,通过脚本标签添加它确实可以在Safari上运行:
<script src="//unpkg.com/@ungap/custom-elements"></script>
Run Code Online (Sandbox Code Playgroud)
但如果我在我的js中导入它仍然不起作用:
import ungapCustomElements from "https://cdn.skypack.dev/@ungap/custom-elements";
Run Code Online (Sandbox Code Playgroud)
我是否使用了错误的 CDN?错误的填充材料?有什么不同?为什么它可以通过脚本标签工作,但不能作为 ES6 导入?
如果相关的话,这是我尝试使用的自定义元素的声明:
class ButtonLink extends HTMLAnchorElement {
connectedCallback() {
console.log("This is not called on Safari");
}
}
customElements.define("button-link", ButtonLink, { extends: "a" });
Run Code Online (Sandbox Code Playgroud) custom-element ×10
javascript ×6
html ×5
angular ×1
cdn ×1
css ×1
dom ×1
es6-modules ×1
html5 ×1
jquery ×1
prototype ×1
rollup ×1
shadow-dom ×1
vue.js ×1
vuejs2 ×1