[2]React 深入浅出-----React的一个高级表格实现功能

来源:互联网 发布:java web快速开发 ide 编辑:程序博客网 时间:2024/06/06 01:56

在我们平常的企业级应用程序里面,表格形式的数据的展现和搜索是非常常见的。一般的做法都是在列表的上面,加几个搜索条件,然后最下面放一个搜索按钮,然后通过调用后台的Ajax进行过滤,然后调用JQuery等其他框架,进行 DOM书的更新,当然这个也是一个好的实现方法,但是就是有一点不太优雅。而且不是所见即所得,比如,必须输入了所有的输入条件,才能进行结构的搜索,而且把数据传输到后端,在传回来,性能上不是特别的好。 那么有没有更好的方法,刚好笔者这段时间在学习React,看到了Stoyan Stefanov写的一本书,里面提到了一种个人感觉比较优雅的方式,而且结合React框架本身的性能优势,我想用户体验应该是挺不错的。




Stoyan的设计的例子如下:

@静态效果:


@动态效果



其具体代码如下:

<!DOCTYPE html><html>  <head>    <title>Table</title>    <meta charset="utf-8">    <link rel="stylesheet" type="text/css" href="03.00.table.css">  </head>  <body>    <div id="app">      <!-- my app renders here -->    </div>    <script src="react/build/react.js"></script>    <script src="react/build/react-dom.js"></script>    <script>      var Excel = React.createClass({        displayName: 'Excel',                propTypes: {          headers: React.PropTypes.arrayOf(            React.PropTypes.string          ),          initialData: React.PropTypes.arrayOf(            React.PropTypes.arrayOf(              React.PropTypes.string            )          ),        },        getInitialState: function() {          return {            data: this.props.initialData,            sortby: null,            descending: false,            edit: null, // [row index, cell index],            search: false,          };        },                _sort: function(e) {          var column = e.target.cellIndex;          var data = this.state.data.slice();          var descending = this.state.sortby === column && !this.state.descending;          data.sort(function(a, b) {            return descending               ? (a[column] < b[column] ? 1 : -1)              : (a[column] > b[column] ? 1 : -1);          });          this.setState({            data: data,            sortby: column,            descending: descending,          });        },                _showEditor: function(e) {          this.setState({edit: {            row: parseInt(e.target.dataset.row, 10),            cell: e.target.cellIndex,          }});        },                _save: function(e) {          e.preventDefault();          var input = e.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,          });        },                _preSearchData: null,                _toggleSearch: function() {          if (this.state.search) {            this.setState({              data: this._preSearchData,              search: false,            });            this._preSearchData = null;          } else {            this._preSearchData = this.state.data;            this.setState({              search: true,            });          }        },                _search: function(e) {          var needle = e.target.value.toLowerCase();          if (!needle) {            this.setState({data: this._preSearchData});            return;          }          var idx = e.target.dataset.idx;          var searchdata = this._preSearchData.filter(function(row) {            return row[idx].toString().toLowerCase().indexOf(needle) > -1;          });          this.setState({data: searchdata});        },                render: function() {          return (            React.DOM.div(null,              this._renderToolbar(),              this._renderTable()            )          );        },                _renderToolbar: function() {          return React.DOM.button(            {              onClick: this._toggleSearch,              className: 'toolbar',            },            'search'          );        },                _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,                  })                );              })            )          );        },                _renderTable: function() {          return (            React.DOM.table(null,              React.DOM.thead({onClick: this._sort},                React.DOM.tr(null,                  this.props.headers.map(function(title, idx) {                    if (this.state.sortby === idx) {                      title += this.state.descending ? ' \u2191' : ' \u2193'                    }                    return React.DOM.th({key: idx}, title);                  }, this)                )              ),              React.DOM.tbody({onDoubleClick: this._showEditor},                this._renderSearch(),                this.state.data.map(function(row, rowidx) {                  return (                    React.DOM.tr({key: rowidx},                      row.map(function(cell, idx) {                        var content = cell;                        var edit = this.state.edit;                        if (edit && edit.row === rowidx && edit.cell === idx) {                          content = React.DOM.form({onSubmit: this._save},                            React.DOM.input({                              type: 'text',                              defaultValue: cell,                            })                          );                        }                        return React.DOM.td({                          key: idx,                          'data-row': rowidx,                        }, content);                      }, this)                    )                  );                }, this)              )            )          );        }      });            var headers = [        "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"],      ];            var Ex = ReactDOM.render(        React.createElement(Excel, {          headers: headers,          initialData: data,        }),        document.getElementById("app")      );    </script>  </body></html>

代码参考:https://github.com/stoyan/react


原创粉丝点击