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

原创 2017年08月06日 22:18:36

在我们平常的企业级应用程序里面,表格形式的数据的展现和搜索是非常常见的。一般的做法都是在列表的上面,加几个搜索条件,然后最下面放一个搜索按钮,然后通过调用后台的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


版权声明:本文为博主原创文章,未经博主允许不得转载。

从零开始的 React 组件开发之路 (一):表格篇

为什么从表格开始呢?在企业系统中,表格是最常见但功能需求最丰富的组件之一,同时也是基于 React 数据驱动的思想受益最多的组件之一,十分具有代表性。这篇文章也是近期南京谷歌开发者大会前端专场的分享总...
  • zl1zl2zl3
  • zl1zl2zl3
  • 2016年07月20日 11:15
  • 2968

一看就懂的ReactJs入门教程(精华版)[转]

一、ReactJS简介 React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的...
  • Dorothy1224
  • Dorothy1224
  • 2016年08月04日 21:52
  • 251

翻译 | 玩转 React 表单 —— 受控组件详解

原文地址:React.js Forms: Controlled Components 原文作者:Loren Stewart 译者:小 B0Y 校对者:珂珂君 本文涵盖以下受控组件: - 文本输入框...
  • u014420383
  • u014420383
  • 2017年07月30日 12:19
  • 670

ReactJS编写的树形表格

表格使用ReactJs编写的树形表格。 表格功能: 以树形表格的格式显示数据; 每条数据的右击菜单根据这条数据中不同的属性标示,可控制对应的类型是否可以下钻; 数据对应的地域下钻之后,点击地域前面的小...
  • wp12345666666
  • wp12345666666
  • 2017年03月14日 17:22
  • 1067

FLEX高级表格MecGrid

前言:几个月前,因为项目需要探索了MecGrid,后来种种原因没有使用。网上的资料不是很多,特意放上来,有兴趣的一起交流学习。本文主要内容参考自MecGrid作者博客:http://www.mecha...
  • lihua2915
  • lihua2915
  • 2010年10月11日 14:09
  • 4332

React学习之高级组件巴巴(二十三)

套路语句 组件是React提供给广大开发者的福利,一可重用,二可装逼,三可事件,简直逆天1.概述·React.Component·是一个抽象基类,因为是抽象类所以如果直接使用·React.Compon...
  • qq_18661257
  • qq_18661257
  • 2017年03月23日 23:03
  • 667

React学习之高级ReactDOM(二十四)

1.概述react-dom中的顶级APIrender() unmountComponentAtNode() findDOMNode() 浏览器支持情况 React支持所有流行的浏览器,包括IE9+...
  • qq_18661257
  • qq_18661257
  • 2017年03月24日 10:18
  • 683

用ReactJs编写的带斜线,行和列都分组的表格

NewUserTrackTable.js文件 /** * Created by Administrator on 2017/3/3 0003. */ import React, {Componen...
  • wp12345666666
  • wp12345666666
  • 2017年03月06日 15:14
  • 249

Apache POI实现数据的Excel导出

POI实现导出数据到excel--------------------------以前也没做过数据导出,公司项目需要就去学习了一下,可能做的不好,然后公司大神直接扔给我一个封装好的帮助类,很方便,不过...
  • JavaReact
  • JavaReact
  • 2017年09月12日 13:26
  • 277

React 入门实践

简介 首先想要介绍的是 React,看到这篇文章的朋友想必都有一些关于 React 的了解了,但对于刚接触的新人而言,在这就要简要地介绍一下了。然后就是关于使用 React 构建一个简单单页应用(下...
  • z69183787
  • z69183787
  • 2016年07月17日 20:29
  • 1678
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[2]React 深入浅出-----React的一个高级表格实现功能
举报原因:
原因补充:

(最多只允许输入30个字)