一个出色的表格,React实现__ES5语法

  本文主要是《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 ></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 ></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>