我创建了一个如下所示的 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) 我一直在阅读,但我没有找到任何东西,如果有可能在不同的 html 文件中定义并使用 ESModule 导入以与 shadowRoot 一起使用,可能吗?
index.html,我在其中定义了 2 个 javscript 模块并使用了我的组件<hello-world></hello-world>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My First Component</title>
<meta name="description" content="My First Component">
<meta name="author" content="Ismael Rodriguez">
<script type="module" src="js/my-template.js"></script>
<script type="module" src="js/component.js"></script>
<!--
<template id="my-template">
<h2>Hello World</h2>
</template>
-->
</head>
<body>
<h1>Web Component</h1>
<hello-world></hello-world>
</body>
Run Code Online (Sandbox Code Playgroud)
js/my-template.js,在这个模块中只导出一个带有标签 html 的字符串。
export const template = `
<style>
h3 {
color: red;
font-family: helvetica;
}
</style>
<h3>Hello World</h3>
`;
Run Code Online (Sandbox Code Playgroud)
js/component.js,最后导入模块my-template.js。我发现这种方法可以使用 ESmodule 从我的模块中解释模板。我如何导入模板并在我的组件中使用(支持 Firefox)? …
github.com/Polymer/lit-element 上的文档描述了生命周期,如果某些 lit-element的属性发生更改。但是,如果元素的 DOM 内容发生更改,我似乎找不到有关生命周期的任何文档。
所以假设我有一些嵌套的 DOM 结构,我最外层的元素应该根据 DOM 内容显示一些东西。为简单起见,下面的示例将仅显示给定类型的子元素的数量。
现在,我的应用程序会插入一个新的嵌套元素(单击test下面的按钮)。在这一点上,我想更新显示的计数。
从我的测试来看,render()在这种情况下似乎不会再次调用,也不会updated()。
我需要监听哪个事件或者我需要实现哪个函数来识别这样的变化?
我目前唯一的解决方法是requestUpdate()在 DOM 更新后手动使用,但我认为此类更改应该由 lit-element 本身处理。
document.querySelector( 'button' )
.addEventListener( 'click', () => {
const el = document.querySelector( 'my-element' );
el.insertAdjacentHTML( 'beforeend', '<my-nested-element>new addition</my-nested-element>' );
})Run Code Online (Sandbox Code Playgroud)
my-element, my-nested-element {
display: block;
}Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
<!-- Works only on browsers that support Javascript modules like Chrome, Safari, Firefox 60, Edge 17 -->
<script type="module">
import {LitElement, html} from …Run Code Online (Sandbox Code Playgroud)我们正在使用 Lit Element 并且我们的组件文件变得相当大,因为我们必须在 .js 文件中编写样式和 html。有没有办法将它们拆分成单独的文件,然后将它们导入到我们的组件中?这样做的最佳方法是什么?HTML 和 CSS 尤其让我们的工作流程变得困难,因为我们的文件变得过于臃肿。
更新:Supersharp 的建议帮助我分离了 CSS 和 html 模板,但我在将 html 模板与指定属性绑定时遇到了问题。我有一个服务文件,它为我指定的文件发出 XML 请求,我将它导入到我的组件文件中。这是我的组件:
import { LitElement, html} from '@polymer/lit-element';
import HtmlLoader from './Service/HtmlLoader';
class TestAnimatedButtonElement extends LitElement {
static get properties() {
return {
_text: {
type: String
}
}
}
constructor() {
super();
this.htmlTemplate = HtmlLoader.prototype.getHtmlTemplate('/src/Components/ExampleElements/test-animated-button-element.html');
}
render(){
this.htmlTemplate.then( template => this.shadowRoot.innerHTML = template)
return html( [this.htmlTemplate] );
}
handleButton(e) {
//e.preventDefault();
console.log('Button pressed');
}
}
customElements.define('test-animated-button-element', TestAnimatedButtonElement);
Run Code Online (Sandbox Code Playgroud)
这是我的 html 文件: …
我有一个简单的 Web 组件,其中包含<slot>. 它处理表单数据,并且在我内部有 UI 元素可以发出数据更改/选定事件。我想知道 web 组件如何对插槽内容发出的事件做出反应。沿着这些路线的东西:
<my-form-handler>
<my-player-selector player-id="master"></my-player-selector>
<my-player-selector player-id="challenger"></my-player-selector>
<my-weapons-selector default="sword"></my-weapons-selector>
</my-form-handler>
Run Code Online (Sandbox Code Playgroud)
我知道我可以编写<my-form-handler ondataSelected="someFunction">假设选择器元素发出dataSelected事件。但这需要代码位于包含页面而不是 my-form-handler 中。
我没有使用任何框架(Vue、Angular、React),只是普通的 JS。
我正在制作 vanilla-js 网络组件,需要将对象作为其值传递给属性,但每次都将其作为字符串。
我能够将字符串传递给组件的属性,但我知道我需要传递一个对象。
var obj = { name: "John", age: 30, city: "New York" };
const template = document.createElement('template');
class TabelComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback() {
console.log(this.content);
}
get content() {
return this.getAttribute("content")
}
}
window.customElements.define('table-component', TabelComponent);Run Code Online (Sandbox Code Playgroud)
<table-component content=obj></table-component>Run Code Online (Sandbox Code Playgroud)
我的属性“内容”应该将 obj 作为对象而不是字符串。我应该进入
{ name: "John", age: 30, city: "New York" };控制台
如果我使用 Lit-element,当前设置全局/重置 CSS 的最佳实践是什么?
我已经尝试过 1) 将它们内联到<style>我的文档根目录中,2) 像这个答案一样构建样式表
<script>
var css = new CSSStyleSheet()
css.replace('@import url("./style/static/reset.css")')
document.adoptedStyleSheets = [css]
</script>
Run Code Online (Sandbox Code Playgroud)
但没有任何作用...
编辑
我的reset.css:
blockquote,
body,
dd,
dl,
fieldset,
figure,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
legend,
p,
pre,
button,
ul {
margin: 0;
padding: 0;
}
img {
max-width: 100%;
}
Run Code Online (Sandbox Code Playgroud)
我建立在来自https://open-wc.org/guide/#quickstart的文件夹结构脚手架之上
我有一个巨大的 Angular 应用程序,其中有几个组件导出为@angular/elements.
这些组件(尽管它们仍然使用共享服务和组件)用于网站的不同部分,该部分不是单页应用程序的一部分,而是由服务器提供的独立页面。
导出的角度元素 在新页面中运行良好,但我认为加载整个 SPA 包(si 5MB+)只是为了渲染两个组件是不可接受的。如何为每个角度元素生成不同的 javascript 文件?
我想像这样渲染我的组件:
<my-first-component />
<script src="./my-first-component.js"></script>
<my-second-component>
<script src="./my-second-component.js"></script>
Run Code Online (Sandbox Code Playgroud)
但是如果页面生成单个包,组件(或者更好的是自定义元素)将不会相互独立!很明显,在这种情况下,串联不起作用。
我怎么解决这个问题?
谢谢
web-component custom-element angular angular-elements angular7
我们的平台建立在带有 Web 组件的微前端架构上。我们正在为其中一些使用 Stencil,这意味着我们在一个网页中有多个 Stencil 应用程序。此外,我们还有一个 UI 库,也是用 Stencil 构建的,我们希望在这些微前端组件中使用它。
我们希望使用 Stencil UI 库作为 Stencil 微前端组件的构建时依赖项。但由于标签名称冲突,目前这是不可能的:
理论上,两个微前端可以提供两个不同版本的 UI 库。但是,在运行时,它们会发生冲突,因为它们都试图用customElements.define. 当然,这不会发生,因为 Stencil 在注册新名称之前检查现有名称 - 但结果同样糟糕:第一个加载的组件总是获胜,如果它是旧版本或具有不同的 API,其他组件会打破。
一个解决方案是在构建或运行时命名空间/前缀标记名称,但网络标准中没有任何内容(尚未)。虽然namespaceStencil 中有一个配置选项,但这似乎并不能解决此类问题。
使用纯 ES6,我们至少可以执行以下操作(即使用动态标签名称注册自定义元素):
export class InnerComponent extends HTMLElement
{
static register(prefix) {
customElements.define(`my-${prefix}-inner-component`, InnerComponent)
}
constructor() {
super()
this.shadow = this.attachShadow({ mode: "open" })
}
connectedCallback() {
this.shadow.innerHTML = `<span>this is some UI component</span>`
}
}
Run Code Online (Sandbox Code Playgroud)
而且我确信我们可以在 Webpack 等中使用某种构建时解决方案来实现相同的目标。
但是 Stencil 是否有类似的可能?或者还有什么办法可以解决这个问题?
我正在创建一个自定义元素,它将能够将其内容从 Markdown 转换为 HTML。但是,我无法获取自定义元素的内容。
<!doctype html>
<html>
<body>
<template id="mark-down">
<div class="markdown"></div>
</template>
<!-- Converts markdown to HTML -->
<script src="https://cdn.jsdelivr.net/gh/showdownjs/showdown/dist/showdown.js"></script>
<script>
customElements.define('mark-down',
class extends HTMLElement {
constructor() {
super()
let template = document.querySelector('#mark-down').content
this.attachShadow({ mode: 'open' }).appendChild(template.cloneNode(true))
}
connectedCallback() {
console.log(this) // Returns the whole <mark-down> node and its contents
console.log(this.innerHTML) // So why does this return a blank string?
// This should theoretically work --> let markdown = this.innerHTML
let markdown = '## Test'
let converter …Run Code Online (Sandbox Code Playgroud)web-component ×10
javascript ×5
angular ×2
html ×2
lit-element ×2
angular7 ×1
dom-events ×1
import ×1
lit-html ×1
module ×1
object ×1
stenciljs ×1