我一直在阅读和尝试一些据我所知可用的 Web 组件实现,但我不喜欢的是它们在 Javascript/JSX/Typescript 中为组件编写 HTML 代码。
我经历过的框架/实现:
Polymer:Polymer 1 和 2 感觉很好,因为他们使用 HTML 导入完成所有定义,并且将 HTML 和 JS 代码分开。但是,对于 Polymer 3,他们也采用类似 React 的语法,在 JS 中编写 HTML,这是我不喜欢的。
Vanilla WebComponents:令人惊讶的是,即使是 Vanilla Web 组件规范也像 React 在 JS 代码中包含 HTML: https: //www.webcomponents.org/introduction再次,这是我不喜欢的。
Stencil:虽然这个工具看起来很有前途,但我仍然遇到同样的问题,我必须在 JS 中编写组件所需的 HTML,然后将其转换为普通 JS。
X-Tag:同样的问题,JS 中的 HTML。
是否有任何实现不需要在 Javascript 中编写 HTML 来使用 Web 组件?
我这样做的主要原因是关注点分离,我无法很好地理解它,因为传统上,网络似乎很好地将骨架、样式和 DOM 操作分离为 HTML、CSS 和 JS 文件,现在,我们将所有内容组合在一起,这感觉对我来说很混乱。
这是我不喜欢 React 的主要原因之一,因为我们在 javascript 中编写类似 HTML 的语法。
我有一个问题,将某些值从父组件传递到子组件并显示该值的最佳方法是什么,因为我尝试使用属性和插槽传递值,并且两种方法都有效。属性:我有一个运动列表,并在父组件中使用repeatlit-html (和html渲染方法),以便创建 n 个子组件,并给出它们属性中的值。
//father component
render(){
return html`
${repeat(movements, movement => movement.id, (movement, index)=> html`
<movement
.id=${movement.id} .description=${movement.description} .amount=${movement.amount} .balance=${movement.balance}>
</movement>
<hr>
`)}
`
}
//child component
render(){
return html`
<dt>${this.id}</dt>
<dl>${this.description}</dl>
<dl>${this.amount}</dl>
<dl>${this.balance}</dl>
`;
}
Run Code Online (Sandbox Code Playgroud)
插槽:我有一个运动列表,并在父组件中使用repeatlit-html (和html渲染方法),以便创建 n 个子组件,并给出在子组件中声明的插槽中的值
//child component
render(){
return html`
<dd>
<slot name="id"></slot>
<slot name="description"></slot>
<slot name="amount"></slot>
<slot name="balance"></slot>
</dd>
`;
}
//father component
render(){
return html`
${repeat(movements, movement=>movement.id, (movement, index)=>html`
<movement>
<dt slot="id"> ${movement.id} </dt> …Run Code Online (Sandbox Code Playgroud) 我正在使用聚合物中的lit-element 建立一个新项目,构建设置包括使用parcel。我还使用打字稿来编写我的代码。
我首先初始化 npm 并添加所有必要的依赖项:
"dependencies": {
"@polymer/lit-element": "^0.6.5",
"@webcomponents/webcomponentsjs": "^2.2.1"
},
"devDependencies": {
"parcel-bundler": "^1.11.0",
"tslib": "^1.9.3",
"typescript": "^3.2.2"
}
Run Code Online (Sandbox Code Playgroud)
现在,当我运行包以 index.html 开始时,其中包括:
@webcomponents/webcomponentsjs/webcomponents-bundle.js
Run Code Online (Sandbox Code Playgroud)
我收到一条错误消息:
Class constructor LitElement cannot be invoked without 'new'
Run Code Online (Sandbox Code Playgroud)
根据其他人的建议,我尝试将 tsconfig 目标设置为“es2016”,但这并不能解决错误。
我的元素.ts
import {
LitElement,
html,
customElement,
property
} from '@polymer/lit-element'
@customElement('ui-text')
export class UiText extends LitElement {
render() {
return html`<p>Hi</p>`
}
}
Run Code Online (Sandbox Code Playgroud) 这是一个小提琴,显示 Chrome 72 和 Firefox 63 中控制台中的错误:
https://jsfiddle.net/jr2z1ms3/1/
代码是:
<script>
customElements.define('test-element', class extends HTMLElement {
constructor() {
super()
Promise.resolve().then(() => {
this.setAttribute('foo', 'bar')
})
}
})
</script>
<test-element>test</test-element>Run Code Online (Sandbox Code Playgroud)
在 Chrome 中,错误是:
Uncaught DOMException: Failed to construct 'CustomElement': The result must not have attributes
Run Code Online (Sandbox Code Playgroud)
在 Firefox 中,错误是:
NotSupportedError: Operation is not supported
Run Code Online (Sandbox Code Playgroud)
如果您对调用进行注释setAttribute,则两个浏览器中的错误都会消失。
以下示例说明了在连接元素之前更改属性,这表明可以使用宏任务来完成此操作,但(不公平地)不能使用微任务来完成:
(下面的片段的工作小提琴)
Uncaught DOMException: Failed to construct 'CustomElement': The result must not have attributes
Run Code Online (Sandbox Code Playgroud)
在第一个示例中,我没有在构造函数中设置属性,而是推迟到未来的微任务。那么为什么浏览器会抱怨呢?如果这是按照规范设计的,那么该规范是否存在“设计错误”?为什么我们不能这样做呢?
根据下面的答案,我不明白为什么需要实施此限制。无论是否存在浏览器引擎限制,糟糕的开发人员仍然可能造成混乱。
IMO,让开发人员决定(并记录)他们的自定义元素如何工作。
如果我们能够在构造函数中或构造函数之后的微任务中设置属性,是否存在浏览器无法克服的技术限制?
我正在尝试用 Angular 编写 Web 组件,但我似乎无法弄清楚如何将数据传递到组件中。
<my-component someId="1234"></my-component>
Run Code Online (Sandbox Code Playgroud)
我希望找到某种方法来实现这一点并在我的角度组件中获取 someId 。是否可以实现这个或者我应该尝试使用插槽?为了清楚起见,我问如何使用角度而不是普通的角度组件来制作网络组件。
给出以下示例代码:
import { LitElement, html, css } from 'lit-element';
class ItemsDisplay extends LitElement {
static get styles() {...}
static get properties {...}
constructor () {
super();
...
}
render {
return html`
${this.items.map((item, index, array) => html`
<div class="name">
...
</div>
`)}
`;
}
}
Run Code Online (Sandbox Code Playgroud)
选择类“name”的所有节点的适当方法是什么?
我尝试过以下方法,但均失败;所有时间nodesList都是undefined:
constructor : this.nodesList = this.shadowRoot.querySelectorAll(".name");
Run Code Online (Sandbox Code Playgroud)
firstUpdated(changedProperties) {
return this.nodesList = this.shadowRoot.querySelectorAll(".name");
}
Run Code Online (Sandbox Code Playgroud)
getNodesList() {
let nodesList = this.shadowRoot.querySelectorAll(".name");
...
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过:
connectedCallback() {
super.connectedCallback(); …Run Code Online (Sandbox Code Playgroud) 我在使用 Material-Web-Component 构建自定义 Lit-Element 组件时确实遇到了问题。即使我确实给了他们必要的 sass/css 类,它们也会堆叠在一起。
我确实想使用顶栏和可扩展抽屉。但内容似乎总是呈现在左上角:/
问题: https: //i.stack.imgur.com/RzVg1.jpg
谁能帮我?:/
应用程序:
import { css, customElement, html, LitElement, property, unsafeCSS } from 'lit-element';
import { router } from '@fhms-wi/router';
const componentCSS = require('./app.component.scss');
@customElement('app-root')
class AppComponent extends LitElement {
static styles = css`${unsafeCSS(componentCSS)}`;
@property()
title = 'Ticket-System';
@property()
headerItems = [
{ title: 'Anmelden', icon: 'sign-in', routePath: 'users/sign-in' },
{ title: 'Konto erstellen', icon: 'sign-up', routePath: 'users/sign-up' }
];
@property()
drawerItems = [
{ title: 'Tickets', icon: 'tickets', routePath: …Run Code Online (Sandbox Code Playgroud) web-component typescript material-design lit-element lit-html
我用 StencilJS 编写了一个 Web 组件。
开槽元素仅应在特定情况下呈现。所以有一个可选元素。
<div>
<slot name="title"/>
{this.active && (<slot name="content"/>)}
</div>
Run Code Online (Sandbox Code Playgroud)
Web组件的调用如下:
<my-test>
<div slot="title">This is a test</div>
<div slot="content">123</div>
</my-test>
Run Code Online (Sandbox Code Playgroud)
这在 Microsoft Edge 和 IE11 中不起作用。对于 Chrome 和 Firefox 来说一切都很好。
我知道插槽不受支持:https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot#Browser_compatibility
但显然 stenciljs 中有一些填充。
有关于该主题的经验吗?
html internet-explorer web-component microsoft-edge stenciljs
该is=""属性是一种通过自定义元素赋予内置元素额外智能的方法,但它似乎只有在自定义元素的 JS 实现扩展了您正在使用它的内置元素时才起作用。
在我看来,将附加功能定义为自定义元素然后将其应用到任何内置元素将非常有用。这将使 Web 组件的用户受益于增强的行为,同时保留标准语义元素的含义。
造成这种限制的原因是什么?
Firefox 似乎确实允许is=""升级内置元素(https://codepen.io/bdhowe/pen/QRLrWQ?editors=1010),但我尝试过的其他浏览器不允许,MDN文档说它可以仅当自定义元素“扩展其所应用的元素类型”时才使用。
class MyElement extends HTMLElement {
constructor() {
super();
var shadow = this.attachShadow({mode: 'open'});
const span = document.createElement('span');
span.textContent = "Hello, world!";
shadow.appendChild(span);
}
}
customElements.define('my-elem', MyElement);
Run Code Online (Sandbox Code Playgroud)
class MyElement extends HTMLElement {
constructor() {
super();
var shadow = this.attachShadow({mode: 'open'});
const span = document.createElement('span');
span.textContent = "Hello, world!";
shadow.appendChild(span);
}
}
customElements.define('my-elem', MyElement);
Run Code Online (Sandbox Code Playgroud)
参考:
我正在使用 Web 组件来构建 Web 应用程序。目前它没有使用任何服务器端代码。尝试加载脚本模块。
<script type="module">
console.log("module");
</script>
Run Code Online (Sandbox Code Playgroud)
这将在桌面浏览器中正常加载。我在控制台中得到了我所期望的结果。对于移动 IOS,此脚本不会输出到控制台
我正在尝试使用脚本模块导入来导入我的自定义元素,这在除 iphone 之外的其他地方都有效。
编辑:我知道 Web 组件与提供的代码没有太大关系。只是我这样做的背景。这是我无法上班的最简单的例子
EDIT2:似乎它运行类型nomodule。
所以现在的问题是:在这些浏览器中运行模块的最佳方式是什么?
发现 Safari 不喜欢在类中声明变量。
class TestElement {
testVar = "test";
}
Run Code Online (Sandbox Code Playgroud)
进入这个
class TestElement {
_constuctor() {
this.testVar = "test;
}
}
Run Code Online (Sandbox Code Playgroud) web-component ×10
javascript ×5
html ×4
lit-element ×4
polymer ×3
lit-html ×2
typescript ×2
angular ×1
components ×1
parcel ×1
shadow-dom ×1
stenciljs ×1