如何获取Web Component 中customElement 创建的对象?

How to get the object created by customElement in a Web Component?

我正在构建一个要在框架中使用的 Web 组件,它嵌入了一个网格库。

我已经设法通过将网格包装在 HTMLElement 中来显示网格 Class

export default class DataGrid extends HTMLElement {    

    constructor() {
        super(); 

        let tmpl = document.createElement('template');
        tmpl.innerHTML = `
            <div id="lib-datagrid"></div>
        `;

        this._shadowRoot = this.attachShadow({mode: "open"});
        this._shadowRoot.appendChild(tmpl.content.cloneNode(true));

        this._rowData = [];

        ...
}

    // Load the grid
    customElements.define('my-grid', DataGrid);     

我需要能够通过 DataGrid 实例将数据传递到 Grid 中。但是,createElements.define() 似乎采用 Class 而不是对象实例,因此我没有创建实例 (new DataGrid()) 并将其传入的选项。

我的理论是我应该能够通过 dom 树检索创建的元素,但我的 Web 组件位于阴影 Dom 中,而我的 Web 组件本身不是 Dom 元素(我认为)即没有“this.getRootNode()”等,但可以访问 documentwindow.

我是不是在 createElement 过程中遗漏了什么,或者有没有办法找到当前影子的根节点 dom?

** 编辑 - 添加顶级 WebComponent 视图

export default (state) => {
const { items, alert, loading } = state;
return (
    <div>       
        <div className="card-top">
            <my-grid></my-grid>
        </div>
    </div>
);

};

** 编辑 2

我发现在线编码 class extends HTMLElement(而不是在单独的 js 文件中)确实允许我更新对象 connectedCallback() 函数的引用。

    let myobject = null;
    
    customElements.define('my-grid2', class extends HTMLElement {
        connectedCallback() {
          const shadow = this.attachShadow({mode: 'open'});
          shadow.innerHTML = `<p>
            Hello
          </p>`;

          myobject = this;
        }
      });  
    

待定其他建议 - 我会处理这个问题,post 如果可行,我会给予答复。

customElements.define('my-grid', DataGrid) 之后,您必须使用以下方法实际创建一个元素:

const elm = document.createElement('my-grid');
const orElm = new DataGrid();

// Use `elm` or `orElm` to pass the data.

如果您的 Web 组件是通过其他方式添加到 DOM 树中的,那么您必须使用 querySelector 或类似方法找到它:

const elm = document.querySelector('my-grid');

但如果它嵌套在其他一些 shadow-root 中,那么 querySelector 将无法执行此操作。为此,您必须精确地找到父元素,获取其阴影根,然后在该阴影根上 运行 querySelector,例如:

const shadowroot = parentElement.shadowRoot;
shadowroot.querySelector('my-grid');

附带说明一下,如果您需要从 Web 组件外部查询或发送数据,那么这可能是代码味道,因为您违反了 封装法则 。还有其他更好的方法可以将数据传递给子组件。否则,你不需要 shadow DOM API。只使用没有阴影的自定义元素 DOM.

我找到了一种方法。

通过在线定义 HTMLElement class 并在 connectedCallback() 函数中处理网格包装器对象,我可以访问 element 的引用创建和 DataGrid 包装器对象。

DataGrid 包装器只需要 shadowRoot 作为构造函数参数创建。

let myElement = null;
let myDataGrid = null;

// Load the grid
customElements.define('my-grid', class extends HTMLElement {
    connectedCallback() {

        let tmpl = document.createElement('template');
        tmpl.innerHTML = `
            <div id="lib-datagrid"></div>
        `;

        const shadow = this.attachShadow({mode: 'open'});
        shadow.appendChild(tmpl.content.cloneNode(true));

        myDataGrid = new DataGrid(shadow);
        myElement = this;
    }
  });    
    

现在我可以稍后调用 DataGrid 对象上的函数来更新数据。

只是为了节省您的输入时间

你可以这么写:

connectedCallback() {

        let tmpl = document.createElement('template');
        tmpl.innerHTML = `
            <div id="lib-datagrid"></div>
        `;

        const shadow = this.attachShadow({mode: 'open'});
        shadow.appendChild(tmpl.content.cloneNode(true));

        myDataGrid = new DataGrid(shadow);
        myElement = this;
    }

如:

connectedCallback() {

        this.attachShadow({mode: 'open'}).innerHTML = `<div></div>`;

        myDataGrid = new DataGrid(this.shadowRoot);
        myElement = this;
    }