自定义一个复杂的React Table表格组件-06

news2025/3/12 22:22:35

前面基本了解了组件的基本用法,在本节会实现一个更高级的例子。另外需要注意本节代码是采用V15版本的createClass()、React.DOM和JSX实现的,有时间的同学可以改成类实现的方式。

html的世界中最复杂的UI控制就是表格了,原因是table它依赖本地环境来创建,不同的系统不同的浏览器对table的实现并不一样,也导致有些功能换了个浏览器不就好用了。

完成后的需要如下:
在这里插入图片描述

基本实现

表头tr实现

表格的结构是 table–> thead --> tr --> td 共4级。

      var Excel = React.createClass({
        // displayName: 'Excel',
        render: function() {
          return (
            React.DOM.table(null,
              React.DOM.thead(null,
                React.DOM.tr(null,
                  this.props.headers.map(function(title, idx) { //map是个工具方法,用于list数据的循环
                    return React.DOM.th({key: idx}, title);
                  })
                )
              )
            )
          );
        }
      });

组件调用,下面的data数据暂时未用。

      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"],
      ];

      ReactDOM.render(
        React.createElement(Excel, {
          headers: headers,
          initialData: data,
        }),
        document.getElementById("app")
      );

在这里插入图片描述

美化表格,添加CSS样式

这个和普通的html写法一样,因为最后所有的元素全会渲染成html代码,比如定义如下样式,然后通过
<link rel="stylesheet" type="text/css" href="table.css"> 引入即可。

td {
  border-top: 1px solid black;
  cursor: cell;
  padding: 5px;
}

th {
  cursor: pointer;
  padding: 5px;
}

table {
  border: 1px solid black;
  margin: 20px;
}

表格td实现

这里实现也比较简单,还是用map循环

    <script>
      var Excel = React.createClass({
        displayName: 'Excel',
        //数据验证
        propTypes: {
          headers: React.PropTypes.arrayOf(
            React.PropTypes.string
          ),
          initialData: React.PropTypes.arrayOf(
            React.PropTypes.arrayOf(
              React.PropTypes.any
            )
          ),
        },

        //绑定state数据,注意表格头数据是死的,所以不添加到state中
        getInitialState() {
          return {data: this.props.initialData};
        },
        
        render: function() {
          return (
            //沉浸表格头
            React.DOM.table(null,
              React.DOM.thead(null,
                React.DOM.tr(null,
                  this.props.headers.map(function(title, idx) {
                    return React.DOM.th({key: idx}, title);
                  })
                )
              ),
              
              //渲染表格内容,根据数据结构循环即可
              React.DOM.tbody(null,
                this.state.data.map(function(row, idx) {
                  return (
                    React.DOM.tr({key: idx},
                      row.map(function(cell, idx) {
                        return React.DOM.td({key: idx}, cell);
                      })
                    )
                  );
                })
              )
            )
          );
        }
      });
      
      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"],
      ];
      
      ReactDOM.render(
        React.createElement(Excel, {
          headers: headers,
          initialData: data,
        }),
        document.getElementById("app")
      );
    </script>

在这里插入图片描述

表格排序

实现的效果是点击表格头,就会按列内容进行排序。核心代码如下:

修改表格头,添加排序事件

React.DOM.table(null,
  React.DOM.thead({onClick: this._sort}, //添加这行代码
    React.DOM.tr(null,
      this.props.headers.map(function(title, idx) {
        return React.DOM.th({key: idx}, title);
      })
    )
  ),

实现排序事件

_sort: function(e) {
  var column = e.target.cellIndex; //得到当前列
  var data = this.state.data.slice(); //得到表格数据副本
  data.sort(function(a, b) {
    return a[column] > b[column] ? 1 : -1; //实现数据排序算法
  });
  this.setState({ //保存数据,重新渲染
    data: data,
  });
},

添加排序视觉响应

其就是给点击的列添加一个图标啥的,比如通过state来拓展:

//添加全局状态
getInitialState: function() {
  return {
    data: this.props.initialData,
    sortby: null,
    descending: 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,
  });
},

//沉浸时添加图标
render: 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)
        )
      ),
    )
  );
}

编辑表格

这个功能实现起来也非常简单,总的来说是就是:1、给单元格加点击事件,确定当前单元格;2、在当前位置添加text控件;3、回传新数据给state;4、删除text控件;

添加点击事件

  getInitialState: function() {
      return {
        data: this.props.initialData,
        sortby: null,
        descending: false,
        edit: null, // [row index, cell index]
      };
  },
  
  React.DOM.tbody({onDoubleClick: this._showEditor}, //点击事件
    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;
            
            //因为是先设计了state,所以会自动重新render,这里会把当前位置添加一个input控件,用form来包裹,借助回车触发保存事件
            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)
  )

在这里插入图片描述

实现点击事件

_showEditor: function(e) {
  this.setState({edit: { //edit为一个自定义属性,需要在 getInitialState()方法中先注册
    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({ //重设数据,再render()
    edit: null,
    data: data,
  });
},

表格搜索

在这里插入图片描述

添加搜索开关

getInitialState: function() {
  return {
    data: this.props.initialData,
    sortby: null,
    descending: false,
    edit: null, // [row index, cell index],
    search: false, //搜索开关
  };
},

因功能代码比较多,所以把原render方法,简单重构一下

render: function() {
  return (
    React.DOM.div(null,
      this._renderToolbar(), //搜索工具栏
      this._renderTable() //原表格实现,搜索框可放在这里实现
    )
  );
}

//声明搜索开关事件
_renderToolbar: function() {
  return React.DOM.button(
    {
      onClick: this._toggleSearch,
      className: 'toolbar',
    },
    'search'
  );
},

//实现开关事件,因为事先把search设置成了一个state数据,所以此值的改变会自动调用render()方法
_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,
    });
  }
},

添加搜索输入框

_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,
          })
        );
      })
    )
  );
},

然后在组件render()方法中添加,即多添加一个返回元素,即在this._renderTable()中添加以下代码。

this._renderSearch(),

实现搜索功能

注意,上述的搜索功能是放在了tr上面来实现的,这样的好处是方便表格定位

_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});
},

数据下载

可下载为json或csv数据,统一做到工具栏中,这里用a标签的原因是html5的新功能,如果链接为一文件则下载文件。

_renderToolbar: function() {
  return  React.DOM.div({className: 'toolbar'},
    React.DOM.button({ //搜索按钮
      onClick: this._toggleSearch,
    }, 'Search'),
    React.DOM.a({ //下载按钮
      onClick: this._download.bind(this, 'json'),
      href: 'data.json',
    }, 'Export JSON'),
    React.DOM.a({ //下载按钮
      onClick: this._download.bind(this, 'csv'),
      href: 'data.csv',
    }, 'Export CSV')
  );
}

功能实现

_download: function(format, ev) {
  //组织数据
  var contents = format === 'json'
    ? JSON.stringify(this.state.data)
    : this.state.data.reduce(function(result, row) {
        return result
          + row.reduce(function(rowresult, cell, idx) {
              return rowresult 
                + '"' 
                + cell.replace(/"/g, '""')
                + '"'
                + (idx < row.length - 1 ? ',' : '');
            }, '')
          + "\n";
      }, '');

  
  //数据封装
  var blob = new Blob([contents], {type: 'text/' + format});
  
  //重设<a>标签的属性实现下载
  var URL = window.URL || window.webkitURL;
  ev.target.href = URL.createObjectURL(blob);
  ev.target.download = 'data.' + format;
},

在这里插入图片描述

下载完整代码

Table.js

<!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 src="babel/browser.js"></script>
    <script type="text/babel">
      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});
        },
        
        _download: function(format, ev) {
          var contents = format === 'json'
            ? JSON.stringify(this.state.data)
            : this.state.data.reduce(function(result, row) {
                return result
                  + row.reduce(function(rowresult, cell, idx) {
                      return rowresult 
                        + '"' 
                        + cell.replace(/"/g, '""')
                        + '"'
                        + (idx < row.length - 1 ? ',' : '');
                    }, '')
                  + "\n";
              }, '');

          var URL = window.URL || window.webkitURL;
          var blob = new Blob([contents], {type: 'text/' + format});
          ev.target.href = URL.createObjectURL(blob);
          ev.target.download = 'data.' + format;
        },
        
        render: function() {
          return (
            <div>
              {this._renderToolbar()}
              {this._renderTable()}
            </div>
          );
        },
        
        _renderToolbar: function() {
          return (
            <div className="toolbar">
              <button onClick={this._toggleSearch}>Search</button>
              <a onClick={this._download.bind(this, 'json')} 
                href="data.json">Export JSON</a>
              <a onClick={this._download.bind(this, 'csv')} 
                href="data.csv">Export CSV</a>
            </div>
          );
        },
        
        _renderSearch: function() {
          if (!this.state.search) {
            return null;
          }
          return (
            <tr onChange={this._search}>
              {this.props.headers.map(function(_ignore, idx) {
                return <td key={idx}><input type="text" data-idx={idx}/></td>;
              })}
            </tr>
          );
        },
        
        _renderTable: function() {
          return (
            <table>
              <thead onClick={this._sort}>
                <tr>{
                  this.props.headers.map(function(title, idx) {
                    if (this.state.sortby === idx) {
                      title += this.state.descending ? ' \u2191' : ' \u2193';
                    }
                    return <th key={idx}>{title}</th>;
                  }, this)
                }</tr>
              </thead>
              <tbody onDoubleClick={this._showEditor}>
                {this._renderSearch()}
                {this.state.data.map(function(row, rowidx) {
                  return (
                    <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 = (
                            <form onSubmit={this._save}>
                              <input type="text" defaultValue={cell} />
                            </form>
                          );
                        }
                        return <td key={idx} data-row={rowidx}>{content}</td>;
                      }, this)}
                    </tr>
                  );
                }, this)}
              </tbody>
            </table>
          );
        }
      });
      
      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>

table.css

html {
  background: white;
  font: 16px Arial;
}

input {
  font: 16px Arial;
}

td {
  border-top: 1px solid black;
  cursor: cell;
  padding: 5px;
}

th {
  cursor: pointer;
  padding: 5px;
}

table {
  border: 1px solid black;
  margin: 20px;
}

.toolbar {
  margin-left: 20px;
}

.toolbar a, .toolbar button { /* thanks css3buttongenerator.com! */
  background: #3498db;
  background-image: linear-gradient(to bottom, #3498db, #2980b9);
  border-radius: 28px;
  box-shadow: 0px 1px 3px #666666;
  color: #ffffff;
  font-size: 14px;
  padding: 10px 20px 10px 20px;
  text-decoration: none;
  border: 0;
  margin-right: 5px;
}

.toolbar a:hover, .toolbar button:hover {
  background: #3cb0fd;
  background-image: linear-gradient(to bottom, #3cb0fd, #3498db);
  text-decoration: none;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1695700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vitis HLS 学习笔记--控制驱动TLP-处理deadlock

目录 1. 简介 2. 代码解析 2.1 HLS kernel代码 2.2 查看接口报告 2.3 TestBench 2.4 Dataflow 报告 3. Takeaways 4. 总结 1. 简介 本文是对《Hardware Acceleration Tutorials: FIFO Sizing for Performance and Avoiding Deadlocks》实验内容的详细解释。 首先需要…

AI视频教程下载:用提示工程在GPT商店构建10个GPTs

你将学到什么&#xff1f; 深入了解ChatGPT平台和GPT商店的生态系统。 开发为多样化应用定制GPT模型的专业知识。 掌握高效内容生成的AI自动化技术。 学习高级提示工程以优化ChatGPT输出。 获取构建AI驱动的数字营销和广告解决方案的技能。 了解如何为SEO写作和优化创建专…

从0开始学统计-多个婴儿连续夭折是谋杀吗?

1.什么是小概率事件&#xff1f; 小概率事件是指在一次随机试验中发生概率非常低的事件。一般来说&#xff0c;小概率事件的发生概率远低于一定的阈值&#xff0c;通常取0.05或0.01。在统计学中&#xff0c;这些阈值被称为显著性水平&#xff08;significance level&#xff0…

CIC滤波器

CIC滤波器结构简单&#xff0c;没有乘法器&#xff0c;只有加法器、积分器和寄存器&#xff0c;适合工作在高抽样率条件下&#xff0c;而且CIC滤波器是一种基于零点相消的FIR滤波器。 CIC滤波器分为单级和多级滤波器。 1.在单极滤波器中&#xff1a; 当CIC滤波器的长度M远大于…

【css3】04-css3转换

目录 1 2D转换 2 3D转换 3 案例&#xff1a;旋转的魔方 1 2D转换 ## 2D转换 ☞ 位移 transform: translate(100px,100px); 备注&#xff1a; 位移是相对元素自身的位置发生位置改变 ☞ 旋转 transform: rotate(60deg); 备注&am…

LabVIEW虚拟测试实验室开发

LabVIEW虚拟测试实验室开发 在当代的科技和工业进步中&#xff0c;测试与测量扮演着至关重要的角色。随着技术的发展&#xff0c;测试系统也变得日益复杂和成本昂贵&#xff0c;同时对测试结果的准确性和测试过程的效率要求越来越高。开发了一种基于LabVIEW的虚拟测试实验室的…

新能源汽车的电驱热管理

前言 新能源汽车的电驱热管理是指维持电动汽车电池、电机和电控系统在适宜的工作温度范围内&#xff0c;保障车辆高效、安全、稳定运行的技术方案。随着新能源汽车的快速发展和普及&#xff0c;电驱热管理技术也日益成为关注焦点。本文将从电池、电机和电控系统三个方面介绍新…

k8s集群的声明式管理资源

一 声明式管理方法 1 适合于对资源的修改操作&#xff08;陈述式方式修改资源非常不方便&#xff09; 2 声明式资源管理方法依赖于yaml资源配置清单文件对资源进行管理 资源配置清单文件有两种格式&#xff1a;yaml&#xff08;人性化&#xff0c;易读&#xff09;&#xff…

中国科学院植物研究所宋献军课题组揭示不同的翻译后修饰协作调控水稻种子大小的新机制

公众号&#xff1a;生信漫谈&#xff0c;获取最新科研信息&#xff01; 中国科学院植物研究所宋献军课题组揭示不同的翻译后修饰协作调控水稻种子大小的新机制https://mp.weixin.qq.com/s/ycNgYzACwkYZbo6k0Zqtcw 未来20年&#xff0c;我国将决战全面建成社会主义现代化国家&…

杰理-耳机进入关机关闭内内置触摸-节省功耗

杰理-耳机进入关机关闭内内置触摸-节省功耗 if (__this->init 0) {return LP_TOUCH_SOFTOFF_MODE_LEGACY; }if ((__this -> softoff_mode LP_TOUCH_SOFTOFF_MODE_ADVANCE) && (__this->softoff_keep 0)) {lp_touch_key_disable(); } __this->softoff_k…

安全设计 | Microsoft 威胁建模工具Threat Modeling Tool安装、使用及威胁生成原理详解(文末附样例)

1. 概览 微软威胁建模工具&#xff08;Threat Modeling Tool&#xff09;是 Microsoft 安全开发生命周期 (SDL&#xff0c;Security Development LifeCycle) 的核心要素。 当潜在安全问题处于无需花费过多成本即可相对容易解决的阶段&#xff0c;软件架构师可以使用威胁建模工…

对vue3/core源码ref.ts文件API的认识过程

对toRef()API的认识的过程: 最开始认识toRef()是从vue3源码中的ref.ts看见的,右侧GPT已经举了例子 然后根据例子,在控制台输出ref对象是什么样子的: 这就是ref对象了,我们根据对象中有没有__v_isRef来判断是不是一个ref对象,当对象存在且__v_isRef true的时候他就判定为是一个…

F28034中断

DSP中断 中断中断概述中断机制 中断 当CPU正在执行程序时&#xff0c;由于发生了某种随机的事件&#xff08;外部或内部&#xff09;&#xff0c;使CPU的执行中断&#xff0c;转而去执行某一段特殊的程序&#xff08;中断子程序或中断处理程序&#xff09;&#xff0c;以处理该…

cs与msf权限传递,以及mimikatz抓取win2012明文密码

目录 解释参数 foreign http foreign https cs与msf权限传递 Cobalt Strike会话传递到Metasploit Framework Cobalt strike上的操作 ​编辑​编辑​编辑 Metasploit Framework上的操作 传递会话 Metasploit Framework会话传递到Cobalt Strike Cobalt strike上的操作…

Tina-Linux -- 3. LVGL测试

参考韦东山 – Tina_Linux_图形系统_开发指南 Tina-linux lvgl 配置 环境配置 进入Tina-SDK根目录 source build/envsetup.sh lunch XXX平台名称 make menuconfigLVGL Gui --->Littlevgl --->< > lv_demo<*> lv_examples &#xff08;lvgl官方demo&#…

监控监测管理系统产品规格说明书(实际原件参考)

【智慧工地】监控监测管理系统产品规格说明书编制模板 一、引言 二、 项目概述 三、 总体需求 四、 功能需求 4.1 概述 4.2 业务功能概要描述 4.3 功能性需求 4.4 功能描述 五、 非功能性需求 5.1 用户界面需求 5.2 软硬件环境需求 5.3 产品质量需求 5.4 接口需求 5.5 其他需求…

HarmonyOS 鸿蒙应用开发 - 多态样式 stateStyles

前言&#xff1a;Styles和Extend仅仅应用于静态页面的样式复用&#xff0c;stateStyles可以依据组件的内部状态的不同&#xff0c;快速设置不同样式&#xff0c;类似于css伪类&#xff0c;但语法不同。 ArkUI提供以下四种状态&#xff1a; focused&#xff1a;获焦态。normal&…

MySQL库/表/数据的操作

文章目录 1.数据库操作1.1 创建、删除、查看和修改1.2 编码格式1.3 备份和恢复 2.表的操作2.1 创建表2.2 存储引擎2.3 查看表、修改表、删除表 3.数据类型3.1整数类型3.2字节类型(bit)3.3浮点类型(bit)3.4 decimal3.5 字符串类型3.6 日期和时间类型3.7 enum和set关于如何查找想…

ES 查询踩坑-全字段匹配

需求&#xff1a;name字段需要全匹配查询 name的映射 普通的must查询 GET power_engin/_search {"from": 0,"size": 10,"query": {"bool": {"must": [{"term": {"name": {"value": "尼…

解决Flutter位于悬浮窗口时,应用Logo不更新问题

问题描述 我已经更换了应用Logo&#xff0c;但是发现应用处于悬浮窗口时&#xff0c;logo还是更改之前的&#xff1f;下面的图片只是示意。 解决方案 终端命令 rm -rf ~/Library/Developer/Xcode/DerivedData2.xcode视图内解决 先在顶部找到 Xcode --> Setting --> Lo…