前言:
最近在学习ReactJS的基本使用,想尝试着做个小东西,加深熟悉。所以就做了个基本的表格,做了个基本的排序功能
用到的知识点:
-
JSX的基本使用(JSX确实方便)
-
React的基本知识:基本控件、事件处理、数据更新。
遇到的难点:
-
子类和父类的通信,由于我把表头和表体分开了,然后通过一个大的Table类,包含了这两个控件。所以当子类触发了事件之后,不能够直接去控制更新它兄弟控件的数据,所以需要通过父控件来做中转。
实现方式:
创建了三个类分别是Thead(用于实现表头)、Tbody(用于实现表体)、Table(包含前两个,共同组成表格)。
细节:
在Thead中绑定点击事件,当触发之后调用,父类的方法。然后通过父类更新Tbody中的数据。
这里没有为Table绑定点击事件,是因为我试了试,没有能够触发(功力不够)。所以放弃了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script src="https://cdn.bootcdn.net/ajax/libs/react/17.0.1/umd/react.development.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <!-- 生产环境中不建议使用 --> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> <title>DEMO</title> </head> <body> <div id="app"> </div> <script type="text/babel"> // 表头数据 var header = ["Book", "Author", "Language", "Published", "Sales"]; // 表体数据 var data = [ [ "The Lord of the Rings", "J. R. R. Tolkien", "English", "1954–1955", "150 million", ], [ "Le Petit Prince (The Little Prince)", "Antoine de Saint-Exupéry", "French", "1943", "140 million", ], [ "Harry Potter and the Philosopher's Stone", "J. K. Rowling", "English", "1997", "107 million", ], [ "And Then There Were None", "Agatha Christie", "English", "1939", "100 million", ], [ "Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1754–1791", "100 million", ], ["The Hobbit", "J. R. R. Tolkien", "English", "1937", "100 million"], [ "She: A History of Adventure", "H. Rider Haggard", "English", "1887", "100 million", ], ]; // 表头实现 class Thead extends React.Component { constructor(props) { super(props); this.state = { header: this.props.header, cellIndex: this.props.cellIndex, }; } render() { return ( <thead> <tr onClick={this.props._headerClick}> {this.state.header.map((value, index) => { return <th key={index}>{value}</th>; })} </tr> </thead> ); } } // 表体实现 class Tbody extends React.Component { constructor(props) { super(props); // 此处设置state,并没有用到。后面使用的是props中的值 this.state = { body: this.props.body, }; } render() { return ( <tbody> {/*需要使用props中的值,对数据进行更新,如果一味的使用state的话,则无法完成数据的更新。 这是因为父类中通过表达式传递的值,是应用到了props中,而不是state中,即便是props在父类类被更新了,子类中的state也不会发生改变。 除非,通知子类更新state数据。但是在这个小Demo中,不需要这么麻烦 */} {this.props.body.map((value, rowKey) => { return ( <tr key={rowKey}> {value.map((colVal, colNum) => { return <td key={colNum}>{colVal}</td>; })} </tr> ); })} </tbody> ); } } // 整体表格的实现 class Table extends React.Component { constructor(props) { super(props); this.state = { headers: this.props.headers, datas: this.props.datas, }; } // 用于让子类调用的方法 f_headerClick = (e) => { this._sort(e.target.cellIndex); }; // 对Tbody中的数据进行排序并更新 _sort(col) { var m_datas = [...this.state.datas]; m_datas.sort((a, b) => { return a[col] > b[col] ? -1 : 1; }); // this.setState({ datas: m_datas, }); } render() { return ( <table> <Thead header={this.state.headers} cellIndex={this.props.cellIndex} _headerClick={this.f_headerClick} /> <Tbody body={this.state.datas} /> </table> ); } } ReactDOM.render( <Table headers={header} datas={data} />, document.getElementById("app") ); </script> </body> </html>