代码之家  ›  专栏  ›  技术社区  ›  Brett Sutton

原始html中的vaadinweb组件

  •  0
  • Brett Sutton  · 技术社区  · 3 年前

    瓦丁23。

    我们将html存储在数据库中,我们需要在vaadin组件中呈现该数据库。

    html包含一个web组件“文本块”

    文本块可以包含嵌套的子项:

    <p>
    <text-block page="PackageSearch" block="empty-search-Sign up for free" class="gimps"> 
        <div class="glimps-tips" id="glimps-tips">
           <h3>Sign up for free</h3> 
           Create a watch and get notifications when a new package version is released.<br>   
        </div>
      </text-block>
    <p>
    

    问题是当 <text-block> 在浏览器中渲染时,子节点被渲染为兄弟节点而不是子节点:

    <p>
    <text-block page="PackageSearch" block="empty-search-Sign up for free" class="gimps"> 
    </text-block>
    <div class="glimps-tips" id="glimps-tips">
       <h3>Sign up for free</h3> 
       Create a watch and get notifications when a new package version is released.<br>   
    </div>
    </p>
    

    我已经将问题归结为Vaadin Element类使用Jsoup这一事实,Jsoup不喜欢web组件,因此作为其“验证”的一部分,它会重新订购组件。

    我相信vaadin正在使用`Element.getOuterHtml()`来完成html的最终渲染,它调用:
      public String getOuterHTML() {
            return ElementUtil.toJsoup(new Document(""), this).outerHtml();
        }
    
    
    我已经尝试创建一个类RawHtml:
    import com.vaadin.flow.component.html.Div;
    
    public class RawHtml extends Div
    {
        private static final long serialVersionUID = 1L;
    
        public RawHtml(String html)
        {
            getElement().setProperty("innerHTML", html);
    
        }
        
        public String html() {
            return getElement().getProperty("innerHTML");
        }
        
        @Override
        public String toString() {
            return html();
        }
    }
    

    然后我使用这个类将html添加到VerticalLayout

    var body = new VerticalLayout();
    body.add(new RawHtml(< html with textblock and nested div as above>);
    

    结果是一样的。div被移动到文本块之外。

    我的理论是,vaadin在将html发送到浏览器之前,使用jsoup对其进行最终渲染。

    我该怎么解决这个问题。

    编辑:根据Leif的建议更新了问题。

    编辑2:

    现在,我已经通过vaadin堆栈将html追溯到UidlRequestHandler.commitJsonResponse中的调用。

    片段传递到 json 的论点 commitJsonResponse 有 div正确地嵌套在文本块中:

    
    
    {"node":267,"type":"put","key":"innerHTML","feat":1,
    "value":"<div>
    <span><p>
    <a href=\"/Blog#link-in-page\">hi</a> 
    <text-block page=\"PackageSearch\" block=\"empty-search-Sign up for free\" class=\"gimps\">\n   
    <div>\n    
    <div class=\"glimps-tips\" id=\"glimps-tips\">\n     
    <h3>Sign up for free</h3> Create a watch and get notifications when a new package version is released.<br> 
    Publish your own private packages.<br> Access your API documentation online.<br> Share packages with your team.<br> 
    Be more productive<br>\n    
    </div>\n   
    </div>\n  
    </text-block>
    

    所以现在看来我的问题不是服务器端,而是客户端。

    以下是浏览器生成内容的屏幕截图:

    enter image description here

    我还可以看到浏览器收到了正确的html:

    enter image description here

    因此,重新排序必须在浏览器上进行。

    vaadin在将html添加到DOM时是否对其进行任何操作?这感觉不太可能。

    这似乎表明浏览器正在重新排序,这表明我的web组件实现是错误的?

    编辑3: 所以我的下一个想法是我的web组件坏了。 为了验证它,我使用这个测试站点: https://stackblitz.com/edit/nested-slots-subkxj?file=my-element.js,index.html,package.json

    进入我的web组件并证明它工作正常(div在插槽中呈现)。

    这是我的web组件:

    
    import { html, LitElement } from 'lit';
    
    export class TextBlock extends LitElement {
    
     
      render() {
        return html`
        <div class='me'>
          <slot name="one"></slot>
        </div>
    
        `;
      }
    }
    customElements.define('text-block', TextBlock);
    
    

    以下是它的渲染方式:

    enter image description here

    0 回复  |  直到 3 年前
        1
  •  2
  •   Leif Åstrand    3 年前

    您没有说明您使用哪个Vaadin组件来呈现HTML内容,所以我假设它是内置的 Html 组成部分该组件使用JSoup来解析HTML,以便能够将HTML的根标记设置为其自己的标记名,而不是将其包装在另一个元素中,然后将HTML的其余部分设置为其自身的内容。

    如果您想让HTML片段按原样传递给浏览器,那么您可以通过创建自己的包装器组件来实现这一点,该组件将原始HTML字符串设置为 innerHTML 通过 Element API

    public class RawHtml extends Div {
      public void setHtml(String html) {
        getElement().setProperty("innerHTML", html);
      }
    }