Code Monkey home page Code Monkey logo

react-gm's Introduction

npm Actions Status

JavaScript Style Guide

About react-gm

愿景:致力于快速搭建项目,像搭积木一样。

为什么叫 gm,因为就职于 观麦。我更喜欢定义为 Get More More Growth。

文档 and demo

Install

npm install react-gm -D

依赖

使用前请保证以下依赖存在

  • react
  • react-dom
  • @svgr/webpack

react-gm's People

Contributors

actions-user avatar chaoming-l avatar chentaochun001 avatar chenzesam avatar deswan avatar fondadam avatar gaaaga avatar gesangs avatar h11g avatar hecatedk avatar heycqing avatar hyhithub avatar joebbchen avatar laamginghong avatar liluo1134 avatar lin2006yuo avatar liyatang avatar nathanhan1 avatar panpana avatar pines-cheng avatar realwate avatar rock-zhang avatar tubulang avatar zhongsink avatar zzzhangrong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

react-gm's Issues

format

应该没啥介绍,看代码

React.Util.format('hello {name}', {name: 'gm'});  // -> hello gm

bug: NProgress

单单执行 NProgress的 end方法的时, 会发生出现一点点进度条,而不是整个进度条

bug分析

由于之前未执行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;
}

Droper

上传文件

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

mark todo

  • 整理 docs @farzer
  • 整理 index.js
  • 整理 Storage
  • webpack2
  • webpack moment
  • searchfilter 重构 搜索框在下拉列表上
  • 检查 PropTypes 的类型,具体到内部,如果是obj
  • 表单支持sm md xs lg
  • 补充字体图标页面
  • 补充浮层的三角标 @fondadam
  • Sheet对子元素undefined的兼容
  • 增加hover tip 组件
  • 清理intro

分页格式规范

本协议由张泽和李雅堂共同敲定,如有错漏留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
    }
}

pagination组件的交互

组件是按约定的规范走,所以直接透传给组件就好,回调 toPage 的第一个参数page直接附到请求Request('xxx').data(Object.assign(data, page)).get() 就好。

SearchSelect手机适配需求

MA邀请码有手机适配需求,而这部分需要用到SearchSelect组件,目前IOS测试确认SearchSelect不适配手机

DatePicker & DateRangePicker

alpha中,求意见

长这样

datepicker

用法

// 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
        });
    }
});

然而,还可以这样

触发datepicker的是其他元素,非input
image

// 注意区别,需要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
        });
    }
});

Calendar

长这样

image

用法

两个参数 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);
    }
});

SearchSelect组件有个bug

bug: 给SearchSelect设置默认值时,若在componentDidMount或者componentWillMount设置好selected,进入页面页面并不会正确显示出默认值selected。(除非你focus一下SearchSelect然后再blur后才能正确显示出默认值selected

看了下源码,发现问题貌似出在这里:
image
image
所以我尝试修改了一下:
image

但demo上貌似没出现这个问题,是因为在constructor就设置好selected了。

Pagination

两种形式,Pagination PaginationText

表现

image

使用

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

PaginationText

同上,只是没有回调

Request

下面提到的约定是一个实验性的尝试,欢迎讨论完善...

是什么

一个封装了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();

约定

  • 返回是json数据
  • 返回格式是
{
code: 0, // 返回码
data: {}, // 任何业务数据数据 {}   []  string  number 等
msg: 'error' // 业务失败的消息
}
  • code等0代表成功。其他代表失败。有些场景code:1代表成功,只需调用code([1])设置。 不过不建议这样处理,最好在data中体现吧。
  • 成功只关心data,失败只关心msg

end

Validate

做校验是件很必须且烦心的事情,需要各种判断,各种正则。
然而正则本身就是件很成本高的理解,复杂的正则可读和维护都不堪。

于是就有了 Validate

使用

举个例子

  • 校验不为空
var Validate from 
// 如果通过校验则返回true,否则返回false
Validate('*', value); 
  • 校验5位数字,至少5位数字,3到5位数字
// 如果通过校验则返回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会随着越来越多的使用而增加更多的内置方法。希望一起来壮大。

Grid

准备

import ReactGM from 'react-gm';
import 'react-gm.css';

grid 组件需要引入样式

表现

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

ValidateMixin

---已经稳定在冲账系统中使用---

先看看应用场景

form

痛点

做校验是个烦人的事情,表单验证就更麻烦了
所以才有了 Validate 和 ValidateMixin

ValidateMixin 连接 form 和 Validate。
Validate专注做校验,ValidateMixin专注校验的展示。

废话好多...

demo

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)

end

就这些...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.