简体   繁体   English

如何访问HTML自定义元素中的内容文本?

[英]How to access content text in HTML Custom Element?

When creating an HTML custom element with a JSON string embedded by the user (though the type of string is not relevant here) ... 创建带有用户嵌入的JSON字符串的HTML自定义元素时(尽管此处字符串的类型无关紧要)...

<my-elem>
  { "some":"content" }
</my-elem>

I would like to JSON.parse it like this ... 我想JSON.parse这样...

class MyElement extends HTMLElement {
    constructor() {
        super();
        this.root = this.attachShadow({ mode:'open' });
        this.root.appendChild(template.content.cloneNode(true));
    }
    connectedCallback() {
        JSON.parse(this.innerHTML);
    }
}
customElements.define('my-elem', MyElement);

const template = document.createElement('template');
template.innerHTML =  `irrelevant`;

... and get a perfect result with Firefox v.63. ...并使用Firefox v.63获得完美的结果。

But running this with Chrome v.71 I get 但是用Chrome v.71运行它

Uncaught SyntaxError: Unexpected end of JSON input

due to this.innerHTML returning an empty string. 由于this.innerHTML返回空字符串。

I also tried other DOM methods to access the textual content, but all of them failed also. 我还尝试了其他DOM方法来访问文本内容,但是所有这些方法也都失败了。

Now I'm rather clueless, how to get this to work with Chrome. 现在,我对如何使它与Chrome一起使用一无所知。

Btw: Using <slot> is of no help, since I do not want to render the textual content ... only access it for parsing. 顺便说一句:使用<slot>并没有帮助,因为我不想呈现文本内容……只能访问它进行解析。

Resolved : 已解决

  • Put the template definition before the class definition. 将模板定义放在类定义之前。
  • Ensure having the script defining the custom element inserted behind all custom element instances in the HTML document. 确保将定义自定义元素的脚本插入HTML文档中所有自定义元素实例的后面。

You should wait for the content to be present. 您应该等待内容出现。

In most cases a simple delay could resolve the problem: 在大多数情况下,只需延迟即可解决问题:

connectedCallback() {
    setTimeout( () => JSON.parse(this.innerHTML) )
}

Alternatly, actually <slot> could help with the slotchange event. 或者,实际上<slot>可以帮助解决slotchange事件。 You can hide the rendering or remove the content if you don't want it. 您可以隐藏渲染或删除内容(如果不需要)。

Why not make it more flexible and support both a src attribute and a data property? 为什么不使其更灵活并同时支持src属性和data属性?

 class MyElement extends HTMLElement { static get observedAttributes() { return ['src']; } constructor() { super(); this.attachShadow({ mode:'open' }); this._data = { name: '', address: '' }; } attributeChangedCallback(attrName, oldVal, newVal) { if (oldVal !== newVal) { const el = this; fetch(newVal).then(resp => resp.json()).then( data => { el._data = data; el.render(); } ); } } render() { this.shadowRoot.innerHTML = ` <div> <div>${this._data.name}</div> <div>${this._data.address}</div> </div>`; } set address(val) { this._data.address = val; this.render(); } set name(val) { this._data.name = val; this.render(); } } customElements.define('my-elem', MyElement); setTimeout(() => { let el = document.querySelector('my-elem'); el.name = 'The Joker'; el.address = 'Gothem'; setTimeout(() => { el.setAttribute('src', 'data:application/json,%7B%22name%22:%22Thanos%22,%22address%22:%22Titan%22%7D') }, 1500); }, 1500); 
 <my-elem src="data:application/json,%7B%22name%22:%22Darth%20Vader%22,%22address%22:%22Death%20Star%22%7D"></my-elem> 

The advantage to using a src attribute is that you can pass in JSON or you can pass in a URL that will return the JSON. 使用src属性的优点是您可以传递JSON,也可以传递将返回JSON的URL。

The properties allow you to change individual values in your DOM. 这些属性允许您更改DOM中的单个值。

Changing the entire innerHTML may not be the right thing to do, but with small amounts of DOM it could be. 更改整个innerHTML可能不是正确的选择,但是只需少量的DOM。 You can also change individual values on the DOM or use something like LitHtml. 您还可以更改DOM上的单个值,或使用类似LitHtml的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM