2019独角兽企业重金招聘Python工程师标准>>>

其实严格意义来说,应该将Pagination(分页处理)和数据加载(AjaxLoad)作为一个独立的组件来处理,不过为了方便展示,就一股脑都做在这个Table里面了。

目前只实现到整个Table的数据加载,不包含单独更新某行某个单元格数据的状态处理。

这一次用到的类库也比较多,这里先汇总一下:

npm install webpack webpack-dev-server react react-dom jquery lodash babel-loader babel-preset-es2015 babel-preset-react babel-plugin-transform-class-properties babel-plugin-transform-es2015-block-scoping babel
-plugin-transform-es2015-computed-properties --save-dev

对,没错,好多,好啰嗦。

先上张预览图:

因为涉及到客户的资料,所以数据打了模糊滤镜了。

这个Table组件包含的特性:

  1. Ajax翻页
  2. 指定checkbox的字段
  3. checkbox翻页会保存(就是多页的checkbox的记录都维持着),这点对于大规模数据校对的时候很必要。
  4. 点击行选中checkbox
  5. 选中行(checkbox)更改行样式
  6. 支持数据排序,实际上数据排序用的是jquery-tablesort,没有嵌入到组件中,一个只有126行的table排序,非常实用。不过其实如果允许单元格数据更新的话,排序就要嵌入在renderTableBodyRows的方法中了。
  7. 有几个基本的事件,onMount,onInit,onRow,onFoot。
  8. 整个Table的操作(翻页)都是无刷新的。

其实要做一个满足各方面使用的Table组件,事情并不简单。除了Table组件外,我还定义了两个公共的方法,并放在了整个项目的入口文件中(webpack的entry),详情如下:

var _ = require('lodash');
var jQuery = require('jquery');
var React = require('react');
var ReactDOM = require('react-dom');window.jQuery = jQuery;
window._ = _;
window.php = require('phpjs');window.filterContent = function filterContent(value, column) {if (_.isObject(value)) {if (_.isArray(value)) {return value;}else if (React.isValidElement(value)) {return value;}else {if (value instanceof Date) {return php.date(column.format || this.props.defaultDateFormat || 'Y-m-d H:i:s', value);}else {return value.toString();}}}if (column) {if (column.options && column.options[value])return column.options[value];else if (column.datetime && value) {var timestamp = php.strtotime(value);if (timestamp > 0)return php.date(column.format || 'Y-m-d H:i', timestamp);return '';}}return value;
};window.tag = function tag(tag, content, props) {return React.createElement(tag, props || {}, filterContent(content));
};var Table = require('./components/Table.jsx');

React开发要点精讲

filterContent函数

filterContent方法,用于过滤指定的内容,这里的过滤指将内容过滤为符合React.isValidElement的内容,并可以嵌入在react的html标签中的内容。

这里其实是React很重要需要掌握的一个技巧。JS中有几种变量的类型:字符、数值、NULL、Boolean、Array、Object。除了Object以外,其他的类型都可以直接插入到react的html中作为内容使用。这里所谓直接插入,包括以下两种形式:

1. html方式(JSX)

<div>{filterContent(content)}</div>

2. 使用React的JS API方法

React.createElement('div', {}, filterContent(content));

尤其注意,所有Object类型,除了React.isValidElement()判断为有效的对象以外,直接用上述两种方法作为标签内容使用,都会抛出React的异常。包括正则表达式和Date对象。

filterContent方法允许传入第二个参数,就是对过滤内容的一些配置参数。这个函数其实是我正式版本的一个缩略版本,但其实已可以用于实用了。

补充说一下,判断为数组的时候,最好打扁遍历这个数组,然后依次将数组元素放入filterContent中执行,最后返回过滤完毕的数组即可,React会进行后续的处理。

tag函数

这个函数其实就是对外讲React.createElement的方法精简化输出实现的一个方法,因为直接生成有状态的DOMElement实在太实用了,让人忍不住想在任意地方去使用。实际上这个方法,就是上面说的创建React HTML标签的方法二。

第一个参数,其实是可以直接传入你自己自定义的React.Component的。

第二个参数就是要插入的内容

第三个参数是这个标签的属性,也就是React组件的props。

获取组件的DOM对象

这里需要粗略的说一下ReactComponent(ReactClass)从实例化->DOM实例化的状态切换。

我们在使用React.createClass或者extends React.Component时,定义大多数的方法和属性,面向的是DOM实例化状态下的对象的方法和属性。

在我们执行React.createElement(或者你直接new ReactComponent)的时候,实际上是创建了这个Component(ReactClass)的普通实例化对象,这个对象并不具备完整的属性(props)、状态(state),以及你所定义的方法。

在React中,并不推荐直接去操作这个普通的实例化对象,也没有提供太多的接口给你去操作。React认为只有渲染到DOM节点树上的对象才是有效的控制对象。如下:

var el = ReactDOM.render(<HelloWorld />, document.getElementById('test'));

ReactDOM.render返回的,才是一个DOM实例化的对象。

而<HelloWorld />则是普通实例化对象。

那么在已经生成了实例化对象的时候,我们该如何获得这个实例化对象所关联的DOM节点呢?

// 接着上一段代码
var domEl = ReactDOM.findDOMNode(el);

但是要注意,React有一套很严密的状态机处理的方法,有效的获取到这个DOM实例化对象的DOM节点,必须确保在componentDidMountcomponentDidUpdate之后,否则也会报异常。

好,今天要讲的内容基本上就到这,下面是Table组件的代码(Table.jsx):

var React = require('react');
var ReactDOM = require('react-dom');
var _ = require('lodash');
var php = require('phpjs');
var $ = require('jquery');class Table extends React.Component {static defaultProps = {columns: {},mergeColumns: {},data: [],pageData: {},pageLinksCount: 10,pageOffset: 1,url: '',ajaxLoad: false,ajaxGetColumns: true,onInit: null,onRow: null,onFoot: null,onMount: null,checkbox: null,checked: [],thEmpty: '未指定表字段',tdEmpty: '未指定表数据',defaultDateFormat: 'Y-m-d H:i:s'};id = 0;updateMount = false;constructor(props) {super(props);this.id = _.uniqueId('table_');this.state = {error: null,ajaxLoading: false,ajaxGetColumns: true,columns: this.props.columns,mergeColumns: this.props.mergeColumns,data: this.props.data,pageData: this.props.data,goPage: 0,checked: this.props.checked};}makeKey() {return this.id + '_' + _.flattenDeep(arguments).join('_');}getCheckboxField() {if (this.props.checkbox && this.state.columns[this.props.checkbox])return 'checkbox_' + this.props.checkbox;return false;}getFields() {var fields = Object.keys(this.state.columns), checkboxField = this.getCheckboxField();if (checkboxField !== false)fields = [checkboxField].concat(fields);return fields;}getColumn(field) {let column = this.state.columns[field] || {}, checkboxField = this.getCheckboxField();if (field === checkboxField) {column.label = <input type="checkbox" value="check_all"onChange={(e) => this.checkAll(e.target.checked)} checked={this.isCheckedAll()}/>}else {if (_.isString(column))column = {label: column};else if (!_.isObject(column))column = {label: field};if (!column.label)column.label = field;if (this.state.mergeColumns[field])column = _.merge(column, this.state.mergeColumns[field]);if (_.isString(column))column = {label: column};else if (!_.isObject(column))column = {label: field};if (!column.label)column.label = field;if (this.state.mergeColumns[field])column = _.merge(column, this.state.mergeColumns[field]);}return column;}loadData(page) {this.setState({ajaxLoading: true});$.ajax({url: this.props.url,data: {columns: this.state.ajaxGetColumns ? 1 : 0,page: page || 1},dataType: 'json'}).success((data) => {data.ajaxGetColumns = false;data.ajaxLoading = false;data.goPage = data.pageData.pageNumber || 1;this.setState(data);}).fail(() => {this.setState({error: '网络错误,请重新尝试!'});})}getData() {return this.state.data || [];}isChecked(item) {return this.getCheckboxField() !== false && this.state.checked.length > 0 && _.indexOf(this.state.checked, item + '') > -1;}isCheckedAll() {var isChecked = false, checkboxField = this.getCheckboxField(), field = this.props.checkbox,data = this.getData(), length = data.length, counter = 0;if (checkboxField === false || this.state.checked.length <= 0)return false;_.each(data, (row) => {if (row[field] && this.isChecked(row[field]))counter += 1;});return counter >= length;}checkAll(isCheck) {var items = [], checkboxField = this.getCheckboxField(), field = this.props.checkbox;if (checkboxField !== false)_.each(this.getData(), function (row) {if (row[field])items.push(row[field]);});return this.checkItem(items, isCheck);}checkItem(item, isCheck) {isCheck = !!isCheck;let checked = this.state.checked;if (!_.isArray(item))item = [item];_.each(item, function (it) {it = it + '';if (isCheck) {if (_.indexOf(checked, it) < 0)checked.push(it);}else {var index = _.indexOf(checked, it);if (index > -1)checked.splice(index, 1);}});this.setState({checked: checked});return this;}checkRow(event, value) {var target = event.target, tag = target.tagName.toLowerCase();if (tag !== 'input' && tag !== 'a' && tag !== 'button') {this.checkItem(value, !this.isChecked(value));}}dom() {return ReactDOM.findDOMNode(this);}changeGoPage(value) {var pageData = this.state.pageData;if (isNaN(value))value = pageData.pageNumber || 1;this.setState({goPage: value});}componentDidMount() {var data = this.getData();if (this.props.ajaxLoad && this.props.url && data.length <= 0)this.loadData(this.props.pageOffset);}componentDidUpdate() {if (this.getData().length > 0 && _.isFunction(this.props.onMount))this.props.onMount.call(this, ReactDOM.findDOMNode(this));}renderTableHead() {return <thead><tr>{this.renderTableHeadCells()}</tr></thead>;}renderTableHeadCells() {let fields = this.getFields(), length = fields.length;if (length <= 0) {if (this.state.ajaxLoading) {return <th>正在获取数据,请稍候……</th>;}return <th><div className="at-table-empty">{filterContent(this.props.tdEmpty)}</div></th>;}return this.getFields().map((field) => {let column = this.getColumn(field), isSort = typeof column.sort === 'undefined' || !!column.sort,className = !isSort || field === this.getCheckboxField() ? 'no-sort' : 'sort-head';return <th key={this.makeKey('head', field)} data-field={field} className={className}>{this.getColumn(field).label}</th>;});}renderTableBody() {return <tbody>{this.renderTableBodyRows()}</tbody>}renderTableBodyRows() {let fields = this.getFields(), data = this.getData(), length = data.length,checkboxField = this.getCheckboxField(), checkbox = this.props.checkbox;if (length <= 0) {if (this.state.ajaxLoading) {return <tr><td><div className="at-ajax-loading">正在加载表数据,请稍候……</div></td></tr>;}return <tr><td><div className="at-table-empty">{filterContent(this.props.tdEmpty)}</div></td></tr>;}if (_.isFunction(this.props.onInit))this.props.onInit.call(this, data);return this.getData().map((row, i) => {var clone = _.clone(row);if (_.isFunction(this.props.onRow)) {this.props.onRow.call(this, row, clone);}return <tr key={this.makeKey('tr', i)}className={clone[checkbox] && this.isChecked(clone[checkbox]) ? 'at-row-checked' : ''}onClick={(e) => this.checkRow(e, clone[checkbox])}>{fields.map((field) => {let value = clone[field] || null;let data = {value: value,text: value,field: field,index: i};if (this.props.onRow[field] && _.isFunction(this.props.onRow[field])) {this.props.onRow[field].call(this, data, row);}if (field === checkboxField) {return <td key={this.makeKey('td', i, field)}data-field={field}><input type="checkbox" value={clone[checkbox]} key={this.makeKey('checkbox_', i, field)}checked={this.isChecked(clone[checkbox])}onChange={(e) => this.checkItem(clone[checkbox], e.target.checked)}/></td>;}else {return <td key={this.makeKey('td', i, field)} data-field={field} data-sort-value={data.value}>{filterContent(data.text, this.getColumn(field))}</td>;}})}</tr>;});}renderTableFoot() {var foot = {data: {},show: false}, fields = this.getFields();if (_.isFunction(this.props.onFoot))this.props.onFoot.call(this, foot);if (foot.show) {return <tfoot><tr className="at-sum-row">{fields.map((field) => {return <td key={this.makeKey('tfoot', field)}>{foot.data[field]}</td>})}</tr></tfoot>;}}renderPagination() {let pageData = this.state.pageData, links = [], tail = [];if (pageData.pageNumber > 0 && pageData.pageSize > 0) {var current = parseInt(pageData.pageNumber), linksCount = parseInt(this.props.pageLinksCount),middle = parseInt(linksCount / 2),total = pageData.pageCount, start = 1, end = linksCount;if (total > linksCount) {if (current >= middle) {start = current - (middle - 1);end = linksCount + start - 1;if (start > 1) {links.push(<li className="pagination-item" key={this.makeKey('page_item_', 1)}><a href={'#page/' + (1)} onClick={() => this.loadData(1)}>{1}</a></li>);end -= 1;}if (start > 2)links.push(<li className="pagination-item pagination-item pagination-omission"key={this.makeKey('page_omission_', 'start')}><span>...</span></li>);}if (end >= total) {start -= end - total;end = total;}else {if (end < total - 1)tail.push(<li className="pagination-item pagination-item pagination-omission"key={this.makeKey('page_omission_', 'end')}><span>...</span></li>);if (end !== total)tail.push(<li className="pagination-item" key={this.makeKey('page_item_', total)}><a href={'#page/' + (total)} onClick={() => this.loadData(total)}>{total}</a></li>);}}for (let i = start; i <= end; i++) {let className = 'pagination-item';if (i == pageData.pageNumber)className += ' pagination-active';let link = <li className={className}key={this.makeKey('page_item_', i)}key={this.makeKey('page_item_', i)}><a href={'#page/' + (i)}onClick={() => this.loadData(i)}>{i}</a></li>;links.push(link);}return <div className="pagination-box"><ul className="pagination-list"><li className="pagination-item">{this.getCheckboxField() ? '选中' + this.state.checked.length + '行,' : ''}{pageData.recordCount && pageData.recordCount > 0 ? '共' + pageData.recordCount + '条记录' : ''}</li>{links.concat(tail)}<li className="pagination-item"><input type="text"value={this.state.goPage}onChange={(e) => this.changeGoPage(e.target.value)}/><a href="#" onClick={() => this.loadData(this.state.goPage)}>跳转</a></li></ul></div>;}}render() {return <div className={this.state.ajaxLoading ? 'at-table-loading' : ''}><table className="at-table">{this.renderTableHead()}{this.renderTableBody()}{this.renderTableFoot()}</table>{this.renderPagination()}</div>;}
}$.fn.table = function (props) {if (!this.get(0))throw new ReferenceError('Invalid DOM Element!');else if (!this.prop('data-table')) {props = props || {};props = _.merge(props, this.data());let input = ReactDOM.render(<Table {...props}/>, this.get(0));this.prop('data-table', input);}return this.prop('data-table');
};module.exports = Table;

这个Table组件,其实是从我的正式项目中抽离出来,并且针对第一阶段使用ReactJS碰到的一些问题重新做了调整和优化。要说的话,可能距离正经的开源还有距离,但自己日常用用还是没啥问题的。

如何调用呢?

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" type="text/css" href="normalize.css"/><link rel="stylesheet" type="text/css" href="font-awesome.css"/><link rel="stylesheet" type="text/css" href="main.css"/>
</head>
<body>
<div id="table_header"></div>
<div id="table_container"></div>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="jquery.tablesort.js"></script><script type="text/javascript">(function() {var $ = jQuery;$(document).ready(function () {var total = 0;function confirmData() {alert('123');}$('#table_container').table({// ajax的数据urlurl: 'http://localhost/ajax/purchase.json',// 是否使用ajax加载ajaxLoad: true,// 数据内容,你可以不填写data,而让ajax来加载// data: [],// 默认页面的当前页,这个也会影响ajax第一次优先加载第几页pageOffset: 1,// 分页的连接显示多少个,实际上无论如何都会按照双数-1,即19 => 19,20 => 19pageLinksCount: 20,// checkbox对应的字段checkbox: 'OrderID',// 已经选中的行checked: ['120014', '120009'],// 表字段的设置,如果ajaxLoad,建议这里留空,附加的字段可以用mergeColumns来设定// columns: {},// 额外附加的字段说明,他会和columns相关的字段的设定内容合并mergeColumns: {DeliveryDate: { datetime: true, format: 'Y-m-d' },OrderDate: { datetime: true, format: 'Y-m-d' },Checked: { options: { 0: tag('strong', '否', { className: 'red' }), 1: tag('strong', '是') } },Valid: { sort: false }},// 初始化接口,这里实际上是渲染到table head的时候,所以这里请不要做任何关于DOM节点的操作onInit: function(data) {total = 0;},// 这里实际上是应该叫做onDataMount,也即,当加载了有效的表数据的时候,才会执行这个结果// 但因为他执行的时机实际上是比React渲染完成要略早的,所以这里执行的内容还是给一个延迟吧onMount: function(dom) {setTimeout(function() {// 这里我们对这个表绑定了一个tablesort的操作,翻页的时候这个tablesort会更新// 但这里就不处理翻页时默认的排序状态了。$($(dom).find('table')).tablesort({}).sort('th.sort-th');}, 500);},// 每一行数据的处理过滤方式,下面这里这个演示的是针对每一行的每一个字段的过滤方式onRow: {// data是一个object,结构为:{ value: value, text: value, field: field, index: rowIndex }// value为原值,text也是原值,但输出的时候会使用text来输出,而不使用value,field是字段名,index是行号// row则是当前行的数据,因为过滤某个单元格的数据时,还是需要使用到行数据的。OrderID: function(data, row) {data.text = tag('strong', data.value);total += parseInt(data.value) || 0;},Valid: function(data, row) {data.text = tag('button', '未核实', { onClick: confirmData });}},// 下面是行数据过滤的另一个版本,这个方式只能针对一行做过滤,两种模式只能任选一种// row是默认的行数据,clone是复制出来的行数据,经过这个接口后,输出的每一行的数据实际上使用的是clone的内容// 所以要通过这里修改输出的内容,请直接修改clone
//              onRow: function(row, clone) {
//
//              },// foot这里只有两个属性:show 是否显示,data 相关显示在tfoot行的数据,一般tfoot主要用来输出汇总的数据内容onFoot: function(foot) {foot.show = true;foot.data = {OrderID: total}}});});}) (jQuery);</script>
</body>
</html>

使用说明已经在注释中了,具体就不做多解释了。

额外补充一些说明,ajax的数据格式:

{"columns": {"id": ["label" => "主键"]},"data": [{"id": 1,"name": "hello"}],"pageData": {"pageCount": 426,"pageNumber": "1","pageParam": "page","pageSize": 20,"recordCount": 8513}
}

后记

其实在过去的2年里,我一直在考虑如何简化后端程序员如何简化操作HTML复杂性的问题。所以在AgiMVC后续的升级版本已经kephp中,都实现了HTML部分的操作函数在内。设计的思想就是用函数名取代繁琐的HTML标签嵌套,并且允许用户实现自定的函数,以实现自定义的标签组合。

而实际上当看到React的时候,我发现自己的想法,和他出发点是很相似的。而React的虚拟化DOM操作,很像我06-07年在某个网站写的一套基于内存操作DOM节点的方法。当然总体而言,React走得更远,还包括了ReactNative。

所以我在对ReactJS有了一个整体性的了解以后,决定入他的坑。

现在前端MVC实在太多,已经进入了前端写模板的时代了。后端程序只要关心数据接口的准确性,前端可以包揽一切。

比起诸多的jade、handlebars、mustcache等js前端模板语言而言,ReactJS最大的优势是保持了HTML与JS混合编写,并实时调用JS变量的内容,没有再经过一层模板系统过滤。这种方式使得你写出来的HTML标签,最终实际上是以JS API的方式保存的,对于团队而言,无非就是有一个写JS的地方而已。而无需额外再去学习一套模板的引擎自己一时脑洞设计出来的模板语言。

保持了DOM节点的另外一个好处就是,能够与HTML规范与时俱进,比如 SVG,这里的好处实在太多。同时还能够因应浏览器的JS引擎升级而升级,完全不需要去改变什么。

当然转用了ReactJS以后,并不能够马上改善后端程序员写HTML的局面,这需要有一个量变到质变的累积。

而经历过这么多年的前端改革洗礼,我已经决定,整个团队的前端的ReactJS组件,由自己的团队成员来写,杜绝使用任何外部插件,因为其实所有的插件,都只是因应一时一刻某一特定环境写成,比如jQuery系列的插件,进入到ReactJS时代,其实80%都可以作废扔掉了。而目前大多数的ReactJS插件,实际上也只是针对某个CSS框架,或者某套UI规范写的,如果哪天你觉得这个CSS看着烦了,要换,基本上全部代码作废。作为UI框架,应该考虑得更远,也应该考虑得更全面。这也包括整个团队的前端打包构建规范,一次性代码、多次性使用的问题。

好吧,随意东拉西扯的,扯远了!

忽然想用ReactJS来写一套替代phpmyadmin的东西,phpmyadmin现行版本实在太扯,各种bug,也敢release,要不要脸了。

转载于:https://my.oschina.net/janpoem/blog/678520

【React教学】通用型DataTable组件——400行内相关推荐

  1. js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable

    js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable 参考文章: (1)js插件---JS表格组件BootstrapTable行内编辑解决方案x-editable ...

  2. bootstrap表格 行编辑状态_JS表格组件BootstrapTable行内编辑解决方案x-editable

    前言:之前介绍bootstrapTable组件的时候有提到它的行内编辑功能,只不过为了展示功能,将此一笔带过了,罪过罪过!最近项目里面还是打算将行内编辑用起来,于是再次研究了下x-editable组件 ...

  3. 通用社区登陆组件技术分享(开源)下篇:OAuth 源码下载及原理解说

    原文http://www.cnblogs.com/cyq1162/archive/2012/11/07/2756848.html 上节内容: 1:通用社区登陆组件技术分享(开源)上篇:OAuth 授权 ...

  4. html5中行内样式写法,react怎么写行内样式?

    react怎么写行内样式?下面本篇文章给大家介绍一下react 行内样式几种写法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. react 行内样式几种写法 法一 这是评论列表组件 ...

  5. 如何通过 Vue+Webpack 来做通用的前端组件化架构设计

    目录:   1. 架构选型     2. 架构目录介绍     3. 架构说明     4. 招聘消息 目前如果要说比较流行的前端架构哪家强,屈指可数:reactjs.angularjs.emberj ...

  6. 程序员接活利器,dataTable组件带你快速开发,摆脱CRUD

    本文摘要 ·对于10,000元以下的外包项目,通常CRUD业务占据50%以上.每个项目虽然业务不同,但是对数据库中每个表的操作都是一定的.在做了n个项目之后,我觉得程序员不能无脑进行CRUD操作,这样 ...

  7. C#.NET 通用权限管理系统组件 大数据多表分页获取部分列的参考方法

    往往我们开发各种信息系统的时候,不只是简单的从一个表读取数据,很可能是从多个表读取数据后,把结果展示在界面上,当遇到2个大表关联时,若技术上没进行一些处理,那分页显示时速度会非常糟糕,在通用权限管理系 ...

  8. 【商业版】C# ASP.NET 通用权限管理系统组件源码中的数据库访问组件可以全面支持Access单机数据库了...

    可能在5年前还用过Access单机数据库但是后来很少用了,可能平时接触的都是大型管理类系统的开发工作大部分是Oracle.SQLServer数据库上做开发的,很少做一些小网站或者单机版本的东西,所以跟 ...

  9. react封装函数_GitHub - daifee/react-component: 用 React 封装一套常用组件

    Daifee-React-Component 用 React 封装一套常用组件 所有组件都是 stateless 组件,但为方便,某些组件提供 API 调用方式的静态方法. [TOC] 使用前须知 源 ...

最新文章

  1. echart 折线图设置y轴单位_echarts折线图有两个图例时如何实现分别采用两个不同单位的y轴...
  2. 理解 Linux 网络栈(2):非虚拟化Linux 环境中的 Segmentation Offloading 技术
  3. MySQL Connector/ODBC 5.2.2 发布
  4. mongo connections url string 的问题
  5. F#基础教程 列表
  6. IOS开发基础之解压缩文件技术
  7. html5和c3属性,H5与C3不得不说的知识点
  8. tensorflow 安装在Anaconda
  9. nodejs express
  10. CentOS 7 gedit编辑器中文乱码解决方法
  11. java date 一个月_java中的日期加一个月的计算
  12. Asp: 解决脚本输出网页出现乱码情况
  13. spring boot2 整合(二)JPA(特别完整!)
  14. 设置sqlplus 显示列数和行数
  15. Android PreferenceActivity设置菜单使用
  16. solidity教程-简介
  17. Java数字转换大写
  18. [转]二阶巴特沃斯(Butterworth)滤波器
  19. 在线LOGO的设计工具推荐
  20. 前苏联切尔诺贝利辐射禁区拍摄到野生水獭吞食鱼

热门文章

  1. 查询数据库中字段内容相同的记录
  2. Android NDK: WARNING: Ignoring unknown import directory:错误解决方法
  3. 大数据之-Hadoop3.x_MapReduce工作流程---大数据之hadoop3.x工作笔记0109
  4. 分表扩展全局序列实际操作_高可用_单表存储千万级_海量存储_分表扩展---MyCat分布式数据库集群架构工作笔记0026
  5. STM32工作笔记0016---MDK开发环境安装
  6. c语言中static使用方法
  7. [mysql] C++操作mysql方法
  8. stl:string:将str中的oldstr替换为newstr
  9. linux底层文件io,学习Rust 文件与 IO
  10. 随想录(fpga处理图像的优缺点)