Handsontable & React

Posted

技术标签:

【中文标题】Handsontable & React【英文标题】: 【发布时间】:2017-10-05 11:35:44 【问题描述】:

我从 react 开始,并尝试在我的 react 应用程序中设置 handsontable: react-handsontable

// import React...
import React from 'react';
import ReactDOM from 'react-dom';

// ... Handsontable with its main dependencies...
import moment from 'moment';
import numbro from 'numbro';
import pikaday from 'pikaday';
import Zeroclipboard from 'zeroclipboard';
import Handsontable from 'handsontable';

// ... and HotTable
import HotTable from 'react-handsontable';

class ExampleComponent extends React.Component 
  constructor(props) 
    super(props);
    this.handsontableData = [
      ["", "Ford", "Volvo", "Toyota", "Honda"],
      ["2016", 10, 11, 12, 13],
      ["2017", 20, 11, 14, 13],
      ["2018", 30, 15, 12, 13]
    ];
  

  render() 
    return (
      <div id="example-component">
        <HotTable root="hot" data=this.handsontableData colHeaders=true rowHeaders=true   stretchH="all" />
      </div>
    );
  

到目前为止工作,但我如何像在纯 javascript 中一样获取表的实例

var ht = new Handsontable(document.getElementById('example1'), options);


ht.setDataAtCell(0, 0, 'new value');

谢谢,蒂姆

【问题讨论】:

【参考方案1】:

如果您尝试访问核心方法,例如“setDataAtCell()”,则可以使用 refs 来访问它们。

例如,将“ref='xyz'”属性添加到 html 元素,然后您可以使用“this.refs.xyz”调用它。我在下面修改了您的示例以进行说明。它添加了一个按钮,onClick 运行一个函数到“setDataAtCell”。

// import React...
import React from 'react';
import ReactDOM from 'react-dom';

// ... Handsontable with its main dependencies...
import moment from 'moment';
import numbro from 'numbro';
import pikaday from 'pikaday';
import Zeroclipboard from 'zeroclipboard';
import Handsontable from 'handsontable';

// ... and HotTable
import HotTable from 'react-handsontable';

class ExampleComponent extends React.Component 
  constructor(props) 
    super(props);
    this.handsontableData = [
      ["", "Ford", "Volvo", "Toyota", "Honda"],
      ["2016", 10, 11, 12, 13],
      ["2017", 20, 11, 14, 13],
      ["2018", 30, 15, 12, 13]
    ];
  

  handleClick(e) 
    this.refs.hot.hotInstance.setDataAtCell(0, 0, 'new value')
  

  render() 
    return (
      <div id="example-component">
        <HotTable root="hot"
                  data=this.handsontableData
                  colHeaders=true
                  rowHeaders=true
                  
                  
                  stretchH="all"
                  ref="hot"
        />
        <br/>
        <button onClick=(e)=>this.handleClick(e)>Click Me</button>
      </div>
    );
  


export default ExampleComponent

此方法可用于访问其他方法,例如“getData()”,可用于获取表中数据的快照,可以保存到状态或类似的数据。所以它比“ht”更长,你可以使用“this.refs.hot.hotInstance”来获得类似的效果。

您可以在 React 文档的“Refs and the DOM”中阅读有关 ref 属性的更多信息。

【讨论】:

谢谢,这对我有用,但 React 现在建议使用 createRef API 而不是直接使用 this.refs (more info)。【参考方案2】:

要访问 HotTable 组件的实例,请使用 ref。但是,不要使用旧的方式来使用 ref。从 16.3 版本开始,React 提供了 2 种方式:

推荐使用 createRef API 使用回调参考 这在早期版本中已经可用,但比 旧的“字符串引用”方式。

我只在这里展示如何使用 createRef :

    在您的构造函数中,添加以下内容:

    this.refToHotIns=React.createRef();
    

    字段属性的名称是任意的,你可以随意命名。

    在您的 render() 方法中,将 JSX 元素更改为:

       <HotTable ref=this.refToHotIns data=this.handsontableData colHeaders=true rowHeaders=true   stretchH="all" />
    

    现在,this.refToHotIns.current 引用挂载的 HotTable 实例。 Handsontable 实例存储在包装组件的 hotInstance 属性下。因此,您可以访问 HotTable 实例的属性/方法,如下所示:

    this.refToHotIns.current.hotInstance.setDataAtCell(0, 0, 'new value');
    

【讨论】:

【参考方案3】:

为handsontable 编写自己的react 包装器非常简单,然后您可以创建对HOT 实例的引用。这是一些示例 React 组件代码:

componentWillReceiveProps( gridSpec ) 

     if (gridSpec) 
        const columns, colHeaders, data = gridSpec;
        const container = document.getElementById(GRID_ID);

        this.hotInstance = new handsontable(container, 
            columns,
            colHeaders,
            data,
            height: 600
        );
    


shouldComponentUpdate () 

    return false;
 

render () 
    return (
        <div style=overflowX: 'hidden', height: '600px'>
            <div id=GRID_ID />
        </div>
    )

【讨论】:

谢谢,我试试这个。 很好的例子,但我认为最好使用 react ref 而不是 grid id【参考方案4】:

您将数据作为构造函数中定义的数组。

this.handsonetableData = [[First row],[second row]]

您可以简单地将这些数据链接到组件内的状态和 setState。它应该非常简单。

this.state = 
  table: [[first line], [second line]]

最终,您可以编写自己的方法来更新该数组的特定值。

constructor (props) 
  super(props)
  this.state = 
    table: [[first row], [second row]]
  

updateValueInTable (row, col, value)
  checkIdontDoAnythingStupid()
  let newTable = this.state.table
  newTable[row][col] = value
  this.setState( table: newTable)

如果您不想使用 state 并使用 redux 之类的东西,您可以将逻辑放在 reducer 中,并将触发器放在 action 中。你来了!

当然取决于你如何检查你是否正确地操作你的数组,很多库可以提供帮助(lodash 和 co。)

【讨论】:

感谢您的回答,但这个窗台并没有给我表格的实例。 sorry Tim,为什么你需要一个 Table 的实例,什么时候可以用数组来控制呢?我要求更好地理解你的问题.. 我需要一个实例才能使用handsontable api,而不仅仅是数据操作。 当您执行排序等操作时,afterchange 事件会为您提供逻辑索引,而不是物理索引。这意味着您正在使用的数据将与状态中的数据不同步。 @Tim,这里是访问数据的方法:handleClick(e) console.log(this.refs.hot.props.data);

以上是关于Handsontable & React的主要内容,如果未能解决你的问题,请参考以下文章

Handsontable 和 NodeJS

如果正则表达式在使用 jQuery 的handsontable 中无效,则禁用按钮

Handsontable 中的 Handsontable 下拉高度调整

从 CSV 导入到 HandsOnTable 并从 HandsOnTable 导出到 CSV

Handsontable 无法正确渲染?

Handsontable 中更新内容数据的问题