我已经定义了一个自定义元素,我只想在自定义元素升级到其注册类型时才执行脚本.用例是我必须调用自定义方法.
我的主要html文件如下所示:
<project-list></project-list>
<script>
var project_list = document.getElementsByTagName("project-list")[0]
project_list.custom_method("some_data");
</script>
Run Code Online (Sandbox Code Playgroud)
自定义元素在HTML导入中注册,如下所示:
<script>
"use strict";
var currentScript = document._currentScript || document.currentScript;
class ProjectList extends HTMLElement {
createdCallback(){
console.log("created");
}
custom_method(data) {
console.log("custom_method() OK");
console.log(data);
this.innerHTML = data;
}
}
document.registerElement("project-list", ProjectList);
</script>
Run Code Online (Sandbox Code Playgroud)
我的问题很简单:如何确保主要html文件中的脚本仅在自定义元素获得其custom_method方法后才被调用?
我正在寻找一个优雅的解决方案.规范作者会想到的东西.我不介意更改架构(例如,如果有必要,可以将javascript从主文件移动到另一个自定义元素中).
未捕获的 DOMException:无法在“CustomElementRegistry”上执行“定义”:此名称已在http://127.0.0.1:8000/components/@polymer/polymer/lib/elements/dom-module.js 上与此注册表一起使用:175:16
尝试删除节点模块和包锁并重新安装不起作用。
我正在玩Aurelia中的自定义元素功能,并试图创建一个'进度条'元素.
进步,bar.js
import {customElement, bindable} from 'aurelia-framework';
@customElement('progress-bar')
export class ProgressBar
{
//do stuff//
}
Run Code Online (Sandbox Code Playgroud)
进步,一个bar.html
<template>
<link rel="stylesheet" type="text/css" href="src/components/progress-bar.css">
<div class='progress-bar' tabindex=0 ref="bar">bloo</div>
</template>
Run Code Online (Sandbox Code Playgroud)
test.html(相关部分)
<require from="./components/progress-bar"></require>
<progress-bar ref="pb">a</progress-bar>
Run Code Online (Sandbox Code Playgroud)
所有这一切都很好.但我正在努力如何让主页可以调用某个函数或更改元素上的某些属性,这应该在进度条本身上做一些事情.
我试图在progress-bar.js中创建一个函数'doSomething',但是我无法在test.js中访问它.
添加到progress-bar.js
doSomething(percent, value) {
$(this.bar).animate('width: ${percent}%', speed);
}
Run Code Online (Sandbox Code Playgroud)
在test.js里面
clicked() {
console.log(this.pb); // this returns the progress bar element fine
console.log(this.pb.doSomething); //this returns as undefined
this.pb.doSomething(percent, value); // this fails outright with error: typeError - doSomething is not a function
}
Run Code Online (Sandbox Code Playgroud)
接下来,我尝试在progress-bar元素中设置自定义属性,并可能使用valueChange来改变div.
里面的进度bar.js
@bindable percent=null;
@bindable speed=null; …Run Code Online (Sandbox Code Playgroud) 我是webcomponents的新手.由于web组件的v1可用,我从那里开始.我已经在网上阅读了关于他们的各种帖子.我对正确编写它们特别感兴趣.我已经阅读了有关插槽并让它们正常工作的信息,尽管我的努力并未导致按照我的预期方式工作的插槽web组件.
如果我编写了这样的嵌套Web组件,嵌套/开槽web组件中的DOM不会插入父级的插槽中:
<parent-component>
<child-component slot="child"></child-component>
</parent-component>Run Code Online (Sandbox Code Playgroud)
这是父webcomponent HTML:
<div id="civ">
<style>
</style>
<slot id="slot1" name="child"></slot>
</div>Run Code Online (Sandbox Code Playgroud)
由于每个web组件(父组件和子组件)都是独立的,因此我一直在创建它们:
customElements.define('component-name', class extends HTMLElement {
constructor() {
super();
this.shadowRoot = this.attachShadow({mode: 'open'});
this.shadowRoot.innterHTML = `HTML markup`
}
})Run Code Online (Sandbox Code Playgroud)
生成的DOM包括2个阴影根.我试图编写没有阴影dom的子/槽元素,这也不会导致托管孩子的父阴影dom.
那么,构建v1嵌套web组件的正确方法是什么?
我有一个简单的Web组件,遵循最新的Web组件v1类语法,它在Chrome和Firefox/Edge(带有polyfill)中运行良好,但我希望它在IE11中运行,所以我需要转换类.然而,通过babel运行它会生成不再适用于任何浏览器的代码.
有没有办法用类语法生成向后兼容的Web组件,还是有一种首选方法来编写Web组件以实现最大兼容性?
示例代码 -
class TestElement extends HTMLElement {
connectedCallback(){
this.innerHTML = "<div>Testing</div>"
}
}
customElements.define('test-element', TestElement)
Run Code Online (Sandbox Code Playgroud)
使用转换代码时出现错误信息是 -
未捕获TypeError:无法构造'HTMLElement':请使用'new'运算符,此DOM对象构造函数不能作为函数调用.
已经有一段时间聚合物版本2可用了,但是
Polymer Project由Google提供支持,团队似乎拥有无可挑剔的理念.
除了缺乏浏览器支持,Polyfills仍然可以正常工作.
顺便说一句,虽然Web组件是Web的标准,但似乎人们不喜欢打开它并继续工作.
对我来说有一个很大的原因,应该有一个解释.
这是我认为与Stackoverflow有关然而我知道很多人不会喜欢这样的问题.
<self-closing /> HTML自定义元素中不允许使用标记.
那是为什么?
很多情况下只需要void标签,我猜想,代码会更具可读性.另一方面,它更直接地暗示语义.
就像<hr />,代码本身意味着里面不应该有任何孩子,因为那里没有地方.此外,它与儿童无关.
自定义元素不能自动关闭,因为HTML只允许一些元素自动关闭.(了解更多)
这实际上是关于ES6中面向对象模型的问题.但是,我将使用创建新的自定义元素作为示例.
因此,创建一个新的自定义元素的新的和有光泽的(截至今天)方法是根据MDN,Google,当然还有规范customElements.define()来获取标签name,a constructor和options(这是可选的).列出的所有文档都使用新关键字的变体.classconstructor
假设我不喜欢新的class语法,并且考虑到大多数情况下class是一个合成糖(根据本教程).该规范甚至具体说明了这一点
无参数调用
super()必须是构造函数体中的第一个语句,以便在运行任何其他代码之前建立正确的原型链和此值.
通过阅读教程,我出来了,试试是否有可能(也修改和重新学习Javascript的对象模型).
var _extends = function(_parent) {
var _result = function() {
_parent.call(this);
};
_result.prototype = Object.create(_parent.prototype);
Object.defineProperty(_result.constructor, 'constructor', {
enumerable: false,
writeable: true,
value: _result
});
return _result;
};
customElements.define('foo-bar', _extends(HTMLElement));
console.log(document.createElement('foo-bar'));
Run Code Online (Sandbox Code Playgroud)
我收到了这个错误
错误:正在构造的自定义元素未注册
customElements.
所以我的问题是,是否可以不使用class关键字(也new可能没有)?如果答案是否定的,我是否应该坚持class使用关键字而不是Object.create在将来编写新的Javascript代码时使用?
我正在尝试创建一个自定义组件来扩展该HTMLInputElement组件,但不会呈现任何内容。
class myInput extends HTMLInputElement {};
customElements.define('my-input', myInput, {
extends: 'input'
});Run Code Online (Sandbox Code Playgroud)
<my-input type="text"></my-input>Run Code Online (Sandbox Code Playgroud)
我在这里想念什么?
2023 年 3 月更新
注意:这是有效的,因为在下一个刻度中,lightDOM 中的N 个(不是全部!)DOM 元素将被解析。
对于 (app.) N > 1000你会遇到麻烦,因为延迟将在解析所有 N 个元素之前结束。
因此,要么添加(大约 20 行)代码来实际检查所有 lightDOM 是否已解析。(但是由于您的 DOM 正在遭受 Obesitas 的困扰,因此您可能还会遇到其他性能问题)
或者只是保持 lightDOM中N 个 DOM 元素的数量较小。
当然,您稍后在解析之后添加的任何 DOM都不会影响任何内容(当不触发时)connectedCallback
2021 年 3 月更新:
FireFox 错误已修复,现在的行为与 Chromium 和 Safari 相同。
这意味着等待 JS EventLoop 为空(带有setTimeout或requestAnimationFrame)现在connectedCallback是一个跨浏览器方法
connectedCallback(){
setTimeout(()=>{
// can access lightDOM here
}); // ,0 not required
}
Run Code Online (Sandbox Code Playgroud)
事件循环到底是什么?- 菲利普·罗伯茨 …
custom-element ×10
javascript ×6
html5 ×3
html ×2
polymer ×2
aurelia ×1
babeljs ×1
callback ×1
class-method ×1
components ×1
es6-class ×1
html-imports ×1
polymer-3.x ×1
shadow-dom ×1