前言:
最近在学习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>