本文主要是《React快速上手开发》一书中,第三章的内容代码整理,因为书中的代码零零散散,所以自己将整理了一下。
排序和编辑功能
<script>
var header = ["Book", "Author", "Language", "Publishd", "Sales"];
var data = [
["The Lord of the Rings", "J. R. R.Tolkien", "English", "1954-1955", "150 million"],
["Le Ptit Prince", "Antonie de Saint-Exupery", "French", "1943", "140 million"],
["Harry Potter and the Philosopher", "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"]
];
var Excel = React.createClass({
displayName :"Excel",
render :function() {
return (
React.DOM.table(null,
React.DOM.thead(
{onClick : this._sort},
React.DOM.tr(
null,
this.state.headers.map(function(title, id){
return React.DOM.th({key: id}, title);
})
)
),
React.DOM.tbody(
{onDoubleClick:this._showEditor},
this.state.data.map(function(row, rowIndex){
return (
React.DOM.tr(
{key:rowIndex},
row.map(function(field, cellIndex){
var content = field;
var edit = this.state.edit;
if (edit && edit.row==rowIndex && edit.cell==cellIndex) {
content = React.DOM.form(
{onSubmit: this._save},
React.DOM.input(
{type : "text", defaultValue : content}
)
);
}
return React.DOM.td(
{key:cellIndex, 'data-row':rowIndex},
content
);
}, this)
)
);
}, this)
)
)
)
},
//点击表头,根据当前列排序
_sort : function(ev){
var column = ev.target.cellIndex;
var data_bk = this.state.data.slice();
data_bk.sort(function(a, b){
return a[column] > b[column] ? 1 : -1;
});
this.setState({
data : data_bk
});
},
getInitialState :function (){
return {
headers : this.props.headers,
data : this.props.initialData,
descending : false,
edit : null
}
},
_showEditor : function(ev){
this.setState({
edit : {
row: parseInt(ev.target.dataset.row, 10),
cell : ev.target.cellIndex
}
});
},
_save : function(ev){
ev.preventDefault();
var input = ev.target.firstChild;
var data = this.state.data.slice();
data[this.state.edit.row][this.state.edit.cell] = input.value;
this.setState({
edit : null,
data : data
});
}
});
ReactDOM.render(
React.createElement(Excel, {headers : header, initialData : data}),
document.getElementById("app")
);
</script>
搜索功能
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>First Test React</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="react/build/react.js"></script>
<script src="react/build/react-dom.js"></script>
<script>
var header = ["Book", "Author", "Language", "Publishd", "Sales"];
var data = [
["The Lord of the Rings", "J. R. R.Tolkien", "English", "1954-1955", "150 million"],
["Le Ptit Prince", "Antonie de Saint-Exupery", "French", "1943", "140 million"],
["Harry Potter and the Philosopher", "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"]
];
var Excel = React.createClass({
displayName :"Excel",
_preSearchData : null,
render :function() {
return (
React.DOM.div(
null,
this._renderToolbar(), //渲染表头和搜索框
this._renderTable() //渲染表格内容
)
)
},
//点击表头,根据当前列排序
_sort : function(ev){
var column = ev.target.cellIndex;
var data_bk = this.state.data.slice();
data_bk.sort(function(a, b){
return a[column] > b[column] ? 1 : -1;
});
this.setState({
data : data_bk
});
},
getInitialState :function (){
return {
headers : this.props.headers,
data : this.props.initialData,
descending : false,
edit : null,
search : false //初始默认关闭搜索功能
}
},
_showEditor : function(ev){
this.setState({
edit : {
row: parseInt(ev.target.dataset.row, 10),
cell : ev.target.cellIndex
}
});
},
_save : function(ev){
ev.preventDefault();
var input = ev.target.firstChild;
var data = this.state.data.slice();
data[this.state.edit.row][this.state.edit.cell] = input.value;
this.setState({
edit : null,
data : data
});
},
_renderToolbar : function() {
return React.DOM.button(
{
onClick : this._toggleSearch, //开启或者关闭搜索功能
className : "toolbar"
},
"search"
);
},
_renderTable : function() {
return (
React.DOM.table(null,
React.DOM.thead(
{onClick : this._sort},
React.DOM.tr(
null,
this.state.headers.map(function(title, id){
return React.DOM.th({key: id}, title);
})
)
),
React.DOM.tbody(
{onDoubleClick:this._showEditor},
this._renderSearch(),
this.state.data.map(function(row, rowIndex){
return (
React.DOM.tr(
{key:rowIndex},
row.map(function(field, cellIndex){
var content = field;
var edit = this.state.edit;
if (edit && edit.row==rowIndex && edit.cell==cellIndex) {
content = React.DOM.form(
{onSubmit: this._save},
React.DOM.input(
{type : "text", defaultValue : content}
)
);
}
return React.DOM.td(
{key:cellIndex, 'data-row':rowIndex},
content
);
}, this)
)
);
}, this)
)
)
)
},
_renderSearch : function() {
if (!this.state.search) {
return null;
}
return (
React.DOM.tr(
{onChange : this._search},
this.props.headers.map(function(_ignore, idx){
return React.DOM.td(
{key : idx},
React.DOM.input(
{type : "text", "data-idx": idx}
)
)
})
)
);
},
//调整搜索功能,如果是开启状态,则关闭它;否则打开搜索功能,通过设置state中的search
_toggleSearch : function() {
if (this.state.search) {
this.setState({
data : this._preSearchData,
search : false
});
this._preSearchData = null;
} else {
this._preSearchData = this.state.data; //开启搜索时,将data先存入_preSearchData
this.setState({
search : true
})
}
},
_search : function (ev) {
var needle = ev.target.value.toLowerCase();
if (!needle) { //搜索的字符串为空时,恢复原数据
this.setState({data : this._preSearchData});
return;
}
var idx = ev.target.dataset.idx; //进行搜索的那一列
var searchData = this._preSearchData.filter(function(row){
return row[idx].toString().toLowerCase().indexOf(needle) > -1;
});
this.setState({
data : searchData
})
}
});
ReactDOM.render(
React.createElement(Excel, {headers : header, initialData : data}),
document.getElementById("app")
);
</script>
</html>
回放功能
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>First Test React</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="react/build/react.js"></script>
<script src="react/build/react-dom.js"></script>
<script>
var header = ["Book", "Author", "Language", "Publishd", "Sales"];
var data = [
["The Lord of the Rings", "J. R. R.Tolkien", "English", "1954-1955", "150 million"],
["Le Ptit Prince", "Antonie de Saint-Exupery", "French", "1943", "140 million"],
["Harry Potter and the Philosopher", "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"]
];
var Excel = React.createClass({
displayName :"Excel",
_preSearchData : null,
_log : [],
render :function() {
return (
React.DOM.div(
null,
this._renderToolbar(), //渲染表头和搜索框
this._renderTable() //渲染表格内容
)
)
},
//点击表头,根据当前列排序
_sort : function(ev){
var column = ev.target.cellIndex;
var data_bk = this.state.data.slice();
data_bk.sort(function(a, b){
return a[column] > b[column] ? 1 : -1;
});
this.setState({
data : data_bk
});
},
getInitialState :function (){
return {
headers : this.props.headers,
data : this.props.initialData,
descending : false,
edit : null,
search : false //初始默认关闭搜索功能
}
},
_showEditor : function(ev){
this.setState({
edit : {
row: parseInt(ev.target.dataset.row, 10),
cell : ev.target.cellIndex
}
});
},
_save : function(ev){
ev.preventDefault();
var input = ev.target.firstChild;
var data = this.state.data.slice();
data[this.state.edit.row][this.state.edit.cell] = input.value;
this.setState({
edit : null,
data : data
});
},
_renderToolbar : function() {
return React.DOM.button(
{
onClick : this._toggleSearch, //开启或者关闭搜索功能
className : "toolbar"
},
"search"
);
},
_renderTable : function() {
return (
React.DOM.table(null,
React.DOM.thead(
{onClick : this._sort},
React.DOM.tr(
null,
this.state.headers.map(function(title, id){
return React.DOM.th({key: id}, title);
})
)
),
React.DOM.tbody(
{onDoubleClick:this._showEditor},
this._renderSearch(),
this.state.data.map(function(row, rowIndex){
return (
React.DOM.tr(
{key:rowIndex},
row.map(function(field, cellIndex){
var content = field;
var edit = this.state.edit;
if (edit && edit.row==rowIndex && edit.cell==cellIndex) {
content = React.DOM.form(
{onSubmit: this._save},
React.DOM.input(
{type : "text", defaultValue : content}
)
);
}
return React.DOM.td(
{key:cellIndex, 'data-row':rowIndex},
content
);
}, this)
)
);
}, this)
)
)
)
},
_renderSearch : function() {
if (!this.state.search) {
return null;
}
return (
React.DOM.tr(
{onChange : this._search},
this.props.headers.map(function(_ignore, idx){
return React.DOM.td(
{key : idx},
React.DOM.input(
{type : "text", "data-idx": idx}
)
)
})
)
);
},
//调整搜索功能,如果是开启状态,则关闭它;否则打开搜索功能,通过设置state中的search
_toggleSearch : function() {
if (this.state.search) {
this.setState({
data : this._preSearchData,
search : false
});
this._preSearchData = null;
} else {
this._preSearchData = this.state.data; //开启搜索时,将data先存入_preSearchData
this.setState({
search : true
})
}
},
_search : function (ev) {
var needle = ev.target.value.toLowerCase();
if (!needle) { //搜索的字符串为空时,恢复原数据
this.setState({data : this._preSearchData});
return;
}
var idx = ev.target.dataset.idx; //进行搜索的那一列
var searchData = this._preSearchData.filter(function(row){
return row[idx].toString().toLowerCase().indexOf(needle) > -1;
});
this.setState({
data : searchData
})
},
_logSetState : function() {
this._log.push(JSON.parse(JSON.stringify(
this._log.length === 0 ? this.state : newState
)));
this.setState(newState)
},
componetDidMount : function() {
document.onkeydown = function() {
if (e.altKey && e.shiftKey && e.keyCode === 82) {
this._replay();
}
}.bind(this);
},
_replay : function() {
if (this._log.length === 0) {
console.log("No state to replay yet");
return;
}
var idx = -1;
var interval = setInterval(function(){
idx++;
if (idx === this._log.length-1){
clearInterval(interval);
}
this.setState(this._log[idx]);
}.bind(this), 1000);
}
});
ReactDOM.render(
React.createElement(Excel, {headers : header, initialData : data}),
document.getElementById("app")
);
</script>
</html>