简体   繁体   English

React 中的 Ag-grid 纯 JS 单元格渲染器

[英]Ag-grid plain JS cell renderer in React

I am using ag-grid in a React application.我在 React 应用程序中使用 ag-grid。 We have pretty heavy duty tables with custom cells.我们有带有自定义单元格的重型表格。 There are performance issues when using custom cell renderers built as React components, which is the most intuitive discourse.使用作为 React 组件构建的自定义单元格渲染器时存在性能问题,这是最直观的论述。

The ag-grid docs state that this is probably not a good idea: ag-grid 文档指出这可能不是一个好主意:

Do NOT use a framework (eg Angular or React) for the cell renderers.不要为单元格渲染器使用框架(例如 Angular 或 React)。 The grid rendering is highly customised and plain JavaScript cell renderers will work faster than framework equivalents.网格渲染是高度定制的,纯 JavaScript 单元格渲染器将比框架等效项更快地工作。

But it also indicates that plain JS can be used in conjunction with frameworks like React:但这也表明纯 JS 可以与 React 等框架结合使用:

It is still fine to use the framework version of ag-Grid (eg for setting ag-Grid properties etc) however because there are so many cells getting created and destroyed, the additional layer the frameworks add do not help performance and should be provided if you are having performance concerns.使用 ag-Grid 的框架版本仍然很好(例如用于设置 ag-Grid 属性等),但是因为有太多的单元被创建和销毁,框架添加的附加层无助于性能,如果您有性能问题。

Am I misinterpreting this?我误解了这个吗? This seems to me that I can use just a plain JS class as a cell renderer (somehow, maybe they'll handle the integration with React?)在我看来,我可以只使用一个普通的 JS 类作为单元格渲染器(不知何故,也许他们会处理与 React 的集成?)

So I took their example code and converted it to a class instead of a function to conform to their typescript definitions:所以我拿了他们的示例代码并将其转换为类而不是函数以符合他们的打字稿定义:

// function to act as a class
class MyCellRenderer {
    eGui: any;
    eButton: any;
    eValue: any;
    eventListener: any;

    init(params: any) {
        // create the cell
        this.eGui = document.createElement('div');
        this.eGui.innerHTML = 
            '<span class="my-css-class"><button class="btn-simple">Push Me</button><span class="my-value"></span></span>';

        // get references to the elements we want
        this.eButton = this.eGui.querySelector('.btn-simple');
        this.eValue = this.eGui.querySelector('.my-value');

        // set value into cell
        this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;

        // add event listener to button
        this.eventListener = function() {
            // tslint:disable-next-line
            console.log('button was clicked!!');
        };
        this.eButton.addEventListener('click', this.eventListener);
    }

    // gets called once when grid ready to insert the element
    getGui() {
        return this.eGui;
    }

    // gets called whenever the user gets the cell to refresh
    refresh(params: any) {
        // set value into cell again
        this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;
        // return true to tell the grid we refreshed successfully
        return true;
    }

    // gets called when the cell is removed from the grid
    destroy() {
        // do cleanup, remove event listener from button
        this.eButton.removeEventListener('click', this.eventListener);
    }
}

// gets called once before the renderer is used

export default MyCellRenderer;

This builds just fine.这构建得很好。 Now when I pull up my table in the app, I get the somewhat predictable error:现在,当我在应用程序中拉出我的桌子时,我得到了一些可预测的错误:

MyCellRenderer(...): Nothing was returned from render. MyCellRenderer(...):渲染没有返回任何内容。 This usually means a return statement is missing.这通常意味着缺少 return 语句。 Or, to render nothing, return null.或者,不渲染任何内容,返回 null。

So it was expecting a React component exclusively?所以它只期待一个 React 组件? It appears that I need to provide the rendering operation anyway.看来无论如何我都需要提供渲染操作。

Does anyone know what's going on here/how to resolve this issue?有谁知道这里发生了什么/如何解决这个问题? Am I misinterpreting the documentation?我误解了文档吗?

Thanks!谢谢!

ps ag-grid is awesome! ps ag-grid 很棒!

Have just worked out how to do it.刚刚想出了怎么做。 There's two sets of 'grid components' properties that you can make available for an instance of a grid for renderers and editors.您可以为渲染器和编辑器的网格实例提供两组“网格组件”属性。

The frameworkComponents property contains ones that will be rendered using the framework you're using, such as React or Angular. frameworkComponents属性包含将使用您正在使用的框架呈现的组件,例如 React 或 Angular。

The components property contains ones that will be rendered using straight JS. components属性包含将使用直接 JS 呈现的属性。

You can mix these however you wish, for example, assuming you have some renderers that have been exported using this pattern:您可以随意混合这些,例如,假设您有一些使用此模式导出的渲染器:

export const XRenderer = {
  id: 'someId',
  renderer: function() ... // or class, or whatever
}
// React components
const frameworkComponents = {
  [CheckboxRenderer.id]: CheckboxRenderer.renderer,
  [SelectRenderer.id]: SelectRenderer.renderer
};

// JavaScript components
const components = {
  [RateRenderer.id]: RateRenderer.renderer
};

<Grid
  columnDefs={columnDefinitions}
  theme={theme}
  rowData={rows}

  frameworkComponents={gridComponents} // React components
  components={components} // JavaScript components

  onGridReady={this.onGridReady}          
  context={this.gridContext}
  gridOptions={this.mainGridOptions}
  ...
/>

The information on how to do this is actually in the docs, but not in a particularly useful place: https://www.ag-grid.com/javascript-grid-components/#mixing-javascript-and-framework有关如何执行此操作的信息实际上在文档中,但不是在一个特别有用的地方: https : //www.ag-grid.com/javascript-grid-components/#mixing-javascript-and-framework

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

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