愿景:致力于快速搭建项目,像搭积木一样。
为什么叫 gm,因为就职于 观麦。我更喜欢定义为 Get More More Growth。
npm install react-gm -D
使用前请保证以下依赖存在
- react
- react-dom
- @svgr/webpack
废弃 迁移到 https://github.com/gmfe/gmfe
愿景:致力于快速搭建项目,像搭积木一样。
为什么叫 gm,因为就职于 观麦。我更喜欢定义为 Get More More Growth。
npm install react-gm -D
使用前请保证以下依赖存在
应该没啥介绍,看代码
React.Util.format('hello {name}', {name: 'gm'}); // -> hello gm
单位由调用方传进去
单单执行 NProgress的 end方法的时, 会发生出现一点点进度条,而不是整个进度条
由于之前未执行start, 则当前container里面的没有 NProgress生成的dom, 执行ReactDom.render的时候,找不到NProgree对应的preComponent, 则不会按照刷新的逻辑执行,即不执行componentWillReceiveProps
当组件生成的时候,state设置成默认的percent属性, percent理解为 从多少百分比开始加载
class NProgress extends React.Component {
constructor(props) {
super(props);
this.state = {
percent: this.props.percent || 0
};
this.timer = null;
}
text...
补充
rt,有时候初始化的时候开始和结束时间需要是空白,等待用户输入。
现在是默认当前日期
import ReactGM from 'react-gm';
import 'react-gm.css';
var Droper = ReactGM.Droper;
var Upload = React.createClass({
render: function () {
return (
<Droper className="gm-droper-wrap" onDrop={this.handleDrop}>
<buttonb className="btn btn-sm">上传</buttonb>
</Droper>
)
},
handleDrop: function (files, event) {
ReactGM.Util.Request('xxxx/url/xxx').data({
file: files[0] // file key 是参数名。问后台要
}).post().then(function(){
// success
});
}
});
没什么好解释的,看代码
/*
Droper.propTypes = {
onDrop: React.PropTypes.func,
onDropAccepted: React.PropTypes.func,
onDropRejected: React.PropTypes.func,
onDragEnter: React.PropTypes.func,
onDragLeave: React.PropTypes.func,
disableClick: React.PropTypes.bool,
multiple: React.PropTypes.bool,
accept: React.PropTypes.string
};
其中accept可以是
image/*
.xlsx
...等等
其中gm-droper-block会包围里面的元素。
*/
var Droper = ReactGM.Droper;
var DroperWrap = React.createClass({
render: function () {
return (
<div>
<Droper onDrop={this.handleDrop} accept="image/*"></Droper>
<Droper className="gm-droper-wrap" onDrop={this.handleDrop} accept=".xlsx">
<button className="btn btn-default">upload</button>
</Droper>
</div>
);
},
handleDrop: function (files, event) {
console.log(arguments);
}
});
本协议由张泽和李雅堂共同敲定,如有错漏留issue
目前发现每个业务都自有一套分页的写法,各不相同,带来接入成本。估借此统一。
offset 位移,从0开始
limit 拉多少条数据,可以近似于一页有多少条数据
count 一共有多少条数据
--------------offset---------------offset+limit---------------------------------------------------->count
请求 url 上带参数 xxxx?offset=0&limit=10
offset 可选,后台默认0
limit 可选,后台默认x,具体看应用。一般是10或者20把。
返回格式
{
code: 0,
data: [ ... ... ],
pagination: {
offset: 10,
limit: 10,
count: 90
}
}
组件是按约定的规范走,所以直接透传给组件就好,回调 toPage 的第一个参数page直接附到请求Request('xxx').data(Object.assign(data, page)).get() 就好。
一些资料 https://juejin.im/entry/59cb25756fb9a00a5d394c84 https://github.com/facebook/react/blob/master/CHANGELOG.md
1 尝试 react@16
2 尝试ReactDOM.createPortal
3 优化dom层级,利用 render 可返回数组特性。
MA邀请码有手机适配需求,而这部分需要用到SearchSelect组件,目前IOS测试确认SearchSelect不适配手机
alpha中,求意见
// date 和 onChange 是必须的
// 因为DatePicker 是内置的,想要定制样式,可以传入 inputClassName ,可以满足需求了
var DatePickerWrap = React.createClass({
getInitialState: function () {
return {
date: new Date()
};
},
render: function () {
return (
<div>
<DatePicker date={this.state.date} onChange={this.handleChange} inputClassName="">
</DatePicker>
</div>
);
},
handleChange: function (date) {
this.setState({
date: date
});
}
});
var DaterangepickerWrap = React.createClass({
getInitialState: function () {
return {
begin: new Date(),
end: new Date()
};
},
render: function () {
return (
<div>
<DateRangePicker begin={this.state.begin} end={this.state.end} onChange={this.handleChange}></DateRangePicker>
</div>
);
},
handleChange: function (begin, end) {
this.setState({
begin: begin,
end: end
});
}
});
// 注意区别,需要target指定触发datepicker的元素
var DatePickerWrap = React.createClass({
getInitialState: function () {
return {
date: new Date()
};
},
render: function () {
return (
<div>
<DatePicker date={this.state.date} onChange={this.handleChange} target={() => this.refs.target}>
<span ref="target">{this.state.date + ''}</span>
</DatePicker>
</div>
);
},
handleChange: function (date) {
this.setState({
date: date
});
}
});
会有告警: Warning: Failed prop type: Required prop popup
was not specified in Trigger
. @liyatang
两个参数 selected onSelect 都不是必须的
var CalendarWrap = React.createClass({
getInitialState: function () {
return {
selected: new Date()
};
},
render: function () {
return (
<div>
<Calendar selected={this.state.selected} onSelect={this.handleSelect}>
</Calendar>
</div>
);
},
handleSelect: function (date) {
this.setState({
selected: date
});
console.log(arguments);
}
});
已私下沟通
两种形式,Pagination PaginationText
var Pagination = ReactGM.Pagination;
var data = {
count: 80,
offset: 10,
limit: 10
};
var onToPage = function (page, index) {
// page={offset, limit} index=1(第几页)
}
var PaginationWrap = React.createClass({
render: function () {
return (
<div>
<Pagination data={gridData} toPage={onToPage}></Grid>
</div>
)
}
});
同上,只是没有回调
下面提到的约定是一个实验性的尝试,欢迎讨论完善...
一个封装了fetch的模块。
平时请求都走$.ajax封装的库,而ajax用的底层XHR。fetch就是想取代XHR,同时减低对jquery的依赖,何乐不为。
国内有介绍
// get
// 返回原生Promise https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
// 成功的数据是原封不动的数据
Request('url').data({id:1}).get();
// post
// 返回原生Promise
Request('url').data({id:1}).post();
get的数据会以url参数形式体现。
post的数据会以表单形式体现。
然而还有post传json字符串的场景,只需data换成json即可
// post json
Request('url').json({id:1}).post();
{
code: 0, // 返回码
data: {}, // 任何业务数据数据 {} [] string number 等
msg: 'error' // 业务失败的消息
}
做校验是件很必须且烦心的事情,需要各种判断,各种正则。
然而正则本身就是件很成本高的理解,复杂的正则可读和维护都不堪。
于是就有了 Validate
举个例子
var Validate from
// 如果通过校验则返回true,否则返回false
Validate('*', value);
// 如果通过校验则返回true,否则返回false
Validate('n5', value);
Validate('n5-', value);
Validate('n3-5', value);
// 如果通过校验则返回true,否则返回false
Validate('m')
// 以下是可重复的
// *:任何字符
// n:数字(只0-9的重复)
// s:字符
// l:字母
// nl: 数字和字母
// zh: 中文
// 以下是某具体类型
// num: 数字 123 0.123
// p:邮政编码
// m:手机号码
// e:email
// url:网址
如果以上规则都没有,你还可以传入正则,不过这没啥意思。后面我们再介绍自定义规则。
Validate(/\d+/, value);
除了校验返回true,false。失败的时候还可以返回具体的错误信息。
// 传递第三个参数true即可
Validate('n5', value, true); // 成功true,失败"请填入5位数字!"
Validate('n5-', value, true); // 成功true,失败"请填入至少5位数字!"
Validate('n3-5', value, true); // 成功true,失败"请填入3到5位数字!"
Validate
是一个函数,其下还有个方法Validate.factory
。
其实上面的规则就是通过Validate.factory
定义的。
Validate.factory('*', function () {
return {
range: true,
rule: '[\\w\\W]',
tip: ['不能为空!', '请填写{min}位任意字符!', '请填写至少{min}位任意字符!', '请填写{min}到{max}位任意字符!']
};
});
Validate.factory('url', function () {
return {
rule: '(\\w+:\\/\\/)?\\w+(\\.\\w+)+.*',
tip: '请填写网址'
};
});
什么用
内置的规则有限,而且很难覆盖业务上的规则。
比如'K12345,K123123'这种很业务的校验只能在业务代码定义了。
我们可以开个validate.gmb.js
模块专门写业务校验。
看到这里,Validate本身很简单,无非就是
Validate会随着越来越多的使用而增加更多的内置方法。希望一起来壮大。
gm-loading-mask 的 z-index 比 gm-framework-top 的z-index还高。
当内容滚动上去的时候,gm-loading-mask挡住了gm-framework-top。
当选择了开始时间,要判断开始时间是否大于结束时间,如果true,修改结束时间 = 开始时间。
或者干脆开始时间不能选择结束时间之后的时间
简言之,开始时间不能大于结束时间。
rt
import ReactGM from 'react-gm';
import 'react-gm.css';
grid 组件需要引入样式
var Grid = ReactGM.Grid;
var renderId = function(value){
return value + ' something';
};
var onClick = function(colValue, index){
// something
};
var isShow = function(colValue, index){
// something
};
var onBatchClick = function(selectCols){
// something
};
var gridData = {
// 是否允许checkbox,配合下面的batchs 使用
enableSelect: true,
// 是否有页码,一共两种形式
enablePagination: true,
enablePaginationText: true,
// load true 表示在拉取数据,此时表格只有thead,tbody是loading图标。
// 注意,loading 为true时优先级高,list有内容也没用,加载完后记得设置回false
loading: true,
// 定义表格数据对应。
// 其中render为一个函数做特殊渲染,参数value。
// 比如 pay_method是1, 可以通过render渲染“线上支付”到界面。
// 比如 date对象,通过render来对date转换成 2015-11-11等。
// 其实对list赋值前做转换就好了啊,为什么要引入render? 建议不修改原数据,数据归数据,展现归展现。
columns: [
{field: 'id', name: 'id', render: renderId},
{field: 'name', name: '名字'},
{field: 'age', name: '年龄'}
],
// 操作。如果提供则表格右侧会出现操作栏。
// click为一个函数,参数该列的数据和索引.
// isShow同上
actions: [{
text: '删除1',
className: 'btn-primary',
click: onClick,
isShow: isShow
}, {
text: '删除2',
click: onClick
}],
// 依赖 enableSelect:true
// batchs是批量操作,click函数提供勾选后的列数据集。
batchs: [{
text: '批量操作',
className: 'btn-primary',
click: onBatchClick
}, {
text: 'adsf',
click: onBatchClick
}],
// grid 的数据原
list: [{
id: 1,
name: '偶们啊啊发*发所发生的',
age: '10'
}, {
id: 1,
name: 'haha',
age: '15'
}],
// 页码部分
pagination: {
count: 80,
offset: 10,
limit: 10
},
// page格式是{offset:20, limit:20}
toPage: function (page) {
console.log(arguments);
}
};
var GridWrap = React.createClass({
render: function () {
return (
<div>
<Grid data={gridData}></Grid>
</div>
)
}
});
---已经稳定在冲账系统中使用---
做校验是个烦人的事情,表单验证就更麻烦了
所以才有了 Validate 和 ValidateMixin
ValidateMixin 连接 form 和 Validate。
Validate专注做校验,ValidateMixin专注校验的展示。
废话好多...
var FormerDom = React.createClass({
mixins: [ValidateMixin()],
onChange: function () {
console.log(arguments);
},
render: function () {
return (
<div style={{width: 300}}>
<form ref="myForm" onSubmit={this.onSubmit}>
<div className="form-group">
<label>email</label>
<input type="text" className="form-control" name="email" onChange={this.validate('e')}/>
<div className="text-danger">{this.validateTip('email')}</div>
</div>
<div className="form-group">
<label>三到5位任意字符</label>
<input type="text" className="form-control" name="height" onChange={this.validate('s3-5')}/>
<div className="text-danger">{this.validateTip('height')}</div>
</div>
<div className="form-group">
<button className="btn btn-default" type="submit">submit</button>
</div>
</form>
<div>
{this.validateTip()}
</div>
</div>
);
},
onSubmit: function (event) {
event.preventDefault();
console.log(this.validateAll(this.refs.myForm));
}
});
首先 ValidateMixin() ,运行一个函数的目的是为了以后更好的扩展。虽然目前没鸟用。
其次,监听onChange变化实时校验。 当然也可以onFocus onBlue 都是ok的。
validate('e') 的 规则 'e' 可以去查看 Validate 组件。
<input type="text" className="form-control" name="email" onChange={this.validate('e')}/>
然后,展示错误信息。 其中 'email' 是具体的 input name。 在表单中设置input的name是个好习惯,而且有很多好处。 Former 中会介绍。
<div className="text-danger">{this.validateTip('email')}</div>
也许你发现了输入框会变红,那是因为如果校验不通过会给元素增加 gm-invalid className,成功就会去掉。
如果你想在某个地方展示表单整体的错误情况。 区别是不提供参数。
this.validateTip()
最后我们要提交表单啦。 当然提交前还是要校验的。
需要提供form 元素的引用。 为啥?原因是某些技术点没摸透,得通过ref去查找使用validate的地方。(求各路大侠献策)
this.validateAll(this.refs.myForm)
就这些...
会出现重复id
解决因权值问题, .gm-xxx 的样式覆盖失败
在页数总共有6页的时候,点击第四页的时候,页码出现了0页标识?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.