- 58金融贷款组ui库
- react
- jest && enzyme(单元测试)
- travis(持续集成)
- 拥抱函数式无状态组件,使组件更加简洁可靠
- 单元测试覆盖率达到80%以上
- 1.render结构是否正常
- 2.检查初始值
- 3.检查点击事件,反馈是否正常
- 4.根据测试覆盖率,作stmts, branch, funcs, lines相应的fill,希望达到70%以上
- /src 存放es6编写的源码
- /lib 存放经过babel编译的es5代码
- /example 存放开发用例代码
- /tool 存放文件编译脚本
- /test 存放单元测试代码
- 安装依赖包
npm install
- 查看用例
npm run example
- 进行单元测试
npm test
- 编译生成lib文件
npm run lib
- 编译生成lib&&dist文件
npm run build
- 对于展示组件来说,多用函数式无状态组件
- 语法简洁性(fb)
- 初始化快(就是一个纯函数,不需要在构建类)首次render性能好
- 占内存少
- 请慎用setState,确保你的每一次setState都确实会体现到UI上
- 每次setState都会引起组件重新渲染,确保你的每一次setState都是有意义的。(性能相关)
- 某些setState前先判断新旧值是否相同
- 请慎将component当作props传入
- 这种方式性能消耗较大
- 推荐这种包裹方式
- 如果是前缀后缀之类的情景,请传入函数式无状态组件
- 请将方法的bind函数一律置于constructor
- 在constructor只需要bind一次,如果在render中每次render都会去执行bind方法(性能相关)
- 请只将组件需要的props传入组件,避免其他不相关props改变引起组件重新渲染
- 避免引起组件不必要的渲染
- 请在希望发生重新渲染的dom或组件上设置唯一key,否则react可能在某些情况下不会重新渲染
- 如果你希望某个状态改变后,这个组件会执行卸载并重建操作,那么请给他一个key(可以用这个改变的状态当key!)否则很有可能会执行更新操作(特定需求场景)
- 慎用太新ES6语法
- 比如:Object.assign进行浅复制(微信上不支持)等...
- 如果一定要用得话,请增加对应polyfile
-
请将jsbundle拆分为几个chunk,进行异步加载。router中内置require.ensure
- 原则上控制主包大小在100KB左右
-
请使用immutable和PureComponent对渲染进行优化,提升项目性能
- 务必一起使用
- immutable不可变数据结构
- PureComponent实质在组件shouldComponentUpdate生命周期中对新旧props,state做了次浅对比
- Dialog
- Toast
- Form
- FormGroup
- Label
- Input
- Switch
- Select
- RadioGroup
- Radio
- CheckboxGroup
- Checkbox
- CheckBtn
- GetCodeBtn
- Button
- List
- Icon
- SvgIcon
- Tabs
- Tab
- TabsFooter
- SortGroup
- Sort
- SelectableListHOC
- ActionSheet
- Carousel
- Slider
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
modelStyle | 遮罩层样式设置 | object | {} | 可选 |
opacity | 背景蒙层透明度 | number | 5 | 可选 |
showState | 展示状态 | bool | false | 必要 |
dialogType | 展示形式 | string | Confirm(Alert CustomPrompt CustomForm Custom) | 必要 |
dialogStyle | 弹窗样式设置 | object | {} | 可选 |
headerType | 弹窗头部展示类型 | string | Alert(Confirm CustomPrompt CustomForm) | 可选 |
headText | 提示头文字 | string | '提示' | 可选 |
headerStyle | 弹窗头部样式设置 | object | {} | 可选 |
contentText | 提示内容文字 | string | '提示内容' | 可选 |
contentStyle | 弹窗内容样式设置 | object | {} | 可选 |
footerTypee | 弹窗底部展示类型 | string | Alert(Confirm Close) | 可选 |
btnLeftText | 左按钮文案 | string | '取消' | 可选 |
btnRightText | 右按钮文案 | string | '确定' | 可选 |
btnLeftCbFun | 左按钮点击时触发的函数 | fun | ()=>{} | 可选 |
btnRightCbFun | 右按钮点击时触发的函数 | fun | ()=>{} | 可选 |
btnCommonFun | 按钮点击触发的共用函数 | fun | ()=>{} | 可选 |
btnCloseFun | 点击关闭按钮时触发的函数 | fun | ()=>{} | 可选 |
<Dialog
dialogType={'Confirm'}
showState={true}
headText={'test head'}
contentText={'提示内容提示内容提示内容'}
btnCommonFun={() => {this.setState({dialogState: false})}}
btnLeftCbFun={() => {console.log('left fun')}}
btnRightCbFun={() => {console.log('right fun')}}/>
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
toastType | toast类型 | string | Hint(Loading Success Fail Netless) | 必要 |
showState | 展示状态 | bool | false | 必要 |
opacity | 背景蒙层透明度 | number | 5 | 可选 |
message | 显示文案 | string | '提示' | 可选 |
timeControl | 配置展示时间 | obj | 无 | 可选 |
<Toast
showState={this.state.showState}
toastType={'Hint'}
opacity={0}
timeControl={{ time: 2000, cbFun: () => {this.setState({showState: false})}}}
message={'提示文字'} />
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
listenRequireMapFun | 监听内部条件验证选项的实时信息 | fun | 无 | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<Form listenRequireMapFun={(mapData) => { console.log(mapData) }} >
...
</Form>
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
groupId | 赋予组内空间id | number or string | 无 | 可选 |
layout | 组内成员布局 | obj | 无 | 可选 |
style | 增加样式 | obj | 无 | 可选 |
children | 子类 | node | 无 | 必要 |
//PropTypes.string
<FormGroup groupId={'inputId'}>
//PropTypes.obj,参照flex布局
<FormGroup layout={{ direction: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | 子类 | node | 无 | 必要 |
style | 增加样式 | obj | 无 | 可选 |
<Label>
<span>姓名</span>
</Label>
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
type | input的类型 | 'input' or 'textarea' | 'input' | 必要 |
value | 输入的值 | all | 无 | 必要 |
defaultText | 默认placeholder | all | '' | 必要 |
onChange | 值更改时触发次函数 | fun | ()=>{} | 必要 |
maxLength | textarea中最大长度,超出文字标红 | number | 200 | 可选 |
validateData | 验证信息 | obj{ promptText: string, validateFun: fun } | 无 | 可选 |
cleanBtn | 右侧清除按钮则配置 | obj{ state: true, cleanFun: fun } | 无 | 可选 |
preffix | 输入框前缀 | node | 无 | 可选 |
suffix | 输入框后缀 | node | 无 | 可选 |
disabled | 是否不可操作 | bool | false | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<Input
type='input'
validateData={{ promptText: '请输入正确的姓名', validateFun: (value) => { return !!value && (value.trim() != '') && /^[\.·\u4e00-\u9fa5]{2,20}$/.test(value); } }}
value={this.state.test5}
cleanBtn={{ state: true, cleanFun: () => {this.setState({test5: ''})} }}
defaultText={'aaa'}
suffix={<GetCodeBtn onClick={() => {}} countNum={60} />} />
onChange={(e) => {this.setState({test5: e.target.value})}} />
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
checked | 选中状态 | bool | false | 必要 |
onChange | 选择时,调用此函数 | fun | 必要 | |
disabled | 是否不可操作 | bool | false | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<Switch
disabled={true}
checked={this.state.checked}
onChange={() => { this.setState({checked: !this.state.checked}) }} />
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
selectedValue | 选中的值 | string or number or bool | 无 | 必要 |
onChange | 选择时,调用此函数 | fun | ()=>{} | 必要 |
optionMap | option信息数组 | array[{ text: string or number, value: string or number }] | [...] | 必要 |
disabled | 是否不可操作 | bool | false | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<Select
selectedValue={this.state.selectVal}
onChange={(e) => {this.setState({selectVal: e.target.value})}}
optionMap={[{text:1, value:1}, {text:2, value:2}, {text:3, value:4}]} />
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
name | Radio的name属性 | string | 无 | 必要 |
selectedValue | 选中的值 | array | [...] | 必要 |
onChange | 选择时,调用此函数 | fun | 无 | 必要 |
style | 增加样式 | obj | 无 | 可选 |
children | 子类 | node | 无 | 必要 |
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
text | 选择项显示的文字 | string or number | 无 | 必要 |
value | 选择项实际的值 | string or number or bool | 无 | 必要 |
preffix | 前缀 | node | 无 | 可选 |
mode | 展现模式 | string | form(button) | 必要 |
uniqueId | 唯一id | string or number | 无 | 可选(如果mode==='button'则必要) |
disabled | 是否不可操作 | bool | false | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<RadioGroup
name={'radioName'}
selectedValue={this.state.radioVal}
onChange={(val) => {this.setState({ radioVal: val }) }}
>
<Radio text={'11'} value={1} />
<Radio text={'22'} value={2} />
<Radio text={'33'} value={3} />
<Radio mode={'button'} uniqueId={111} text={'44'} value={4} />
</RadioGroup>
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
name | Checkbox的name属性 | string | 无 | 必要 |
selectedValue | 选中的值 | array | [...] | 必要 |
onChange | 选择时,调用此函数 | fun | 无 | 必要 |
style | 增加样式 | obj | 无 | 可选 |
children | 子类 | node | 无 | 必要 |
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
text | 选择项显示的文字 | string or number | 无 | 必要 |
value | 选择项实际的值 | string or number or bool | 无 | 必要 |
preffix | 前缀 | node | 无 | 可选 |
mode | 展现模式 | string | form(button) | 必要 |
uniqueId | 唯一id | string or number | 无 | 可选(如果mode==='button'则必要) |
disabled | 是否不可操作 | bool | false | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<CheckboxGroup
name={'checkboxName'}
selectedValue={this.state.checkboxVal}
onChange={(val) => {console.log(`checkbox/${val}`); this.setState({ checkboxVal: val })}}>
<Checkbox text={'11'} value={1} />
<Checkbox text={'22'} value={2} />
<Checkbox text={'33'} value={3} />
<Checkbox mode={'button'} uniqueId={111} text={'22'} value={2} />
</CheckboxGroup>
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
btnMap | 选择按钮的信息 | array[{ text: string or number, value: string or number }] | [...] | 必要 |
selectedValue | 被选中的值 | string or number or bool | 无 | 必要 |
onChange | 选择时,调用此函数 | func | ()=>{} | 必要 |
disabled | 是否不可操作 | bool | false | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<CheckBtn
btnMap={[{ text: '有', value: true }, { text: '无', value: false }]}
selectedValue={this.state.checkBtn}
onChange={(val) => {this.setState({ checkBtn: val })}} />
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
text | 按钮显示的文字 | string | '获取验证码' | 可选 |
countNum | 倒计时时间 | number | 60 | 可选 |
onClick | 点击时调用的函数 | func | () => {} | 可选 |
disabled | 是否不可操作 | bool | false | 可选 |
style | 增加样式 | obj | 无 | 可选 |
<GetCodeBtn
text={ '获取验证码'}
countNum={60}
onClick={() => {}} />
- props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
size | 按钮大小 | string(small,big,long) | small | 可选 |
type | 按钮类型 | string(primary,colorfulHollow,grayHollow) | primary | 可选 |
icon | 按钮内图标地址 | string | 空 | 可选 |
isDisabled | 是否禁用 | bool | false | 可选 |
isRadius | 是否有圆角 | bool | true | 可选 |
onClick | 点击事件 | func | ()=>{} | 可选 |
<Button
size='small'
btnType='primary'
onClick={(e)=>{this.callbackFun(e)}}
>开关按钮</Button>
-
desc
普通icon,可自定义添加属性className,style,或在中添加任意inline或inline-block元素。
默认inline-block区域大小:20px*20px
-
props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | 任意inline或inline-block元素 | node | 无 | 可选 |
其他属性(eg: className等未在文档中声明的属性),也可加到当前元素上
<Icon className="demo-icon-test" style={{color: 'red'}}>
<img />
...
</Icon>
-
desc
svgIcon
默认svg区域大小:20px*20px
-
props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | 任意有效的svg图形路径 | node | 无 | 可选 |
viewBox | 设定svg内图形展示范围 | string | '0 0 20 20' | 可选 |
color | svg内图形填充色,对应style中的fill | string | '#333' | 可选 |
其他属性(eg: className等未在文档中声明的属性),也可加到当前元素上
<SvgIcon className="test" color="#333" viewBox="0 0 20 20">
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
</SvgIcon>
- Tabs props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | node | 可选 | ||
value | 选中和当前value匹配的tab.当设置value且与相应的tab匹配,则initSelectedIndex无效 | string | 可选 | |
onSelectedChange | 选中项改变时触发.参数(value, tab) | func | () => {} | 可选 |
initSelectedIndex | 初始选中的tab index | number | 0 | 可选 |
其他属性(eg: className等未在文档中声明的属性),也可加到当前元素上
- Tab props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | 任意html元素,即当前tab下的内容 | node | 可选 | |
value | 用于标识唯一的tab,不能重复 | string | 可选 | |
label | tab文字 | string | 是 | |
icon | icon图标 | node | 可选 | |
onSelectAction | 当前选中某项触发.参数(tab) | func | () => {} | 可选 |
其他属性(eg: className等未在文档中声明的属性),也可加到当前元素上
<Tabs value='a' initSelectedIndex={0}>
<Tab value='a'>
<p>content</p>
</Tab>
<Tab value='b'/>
...
<Tab value='c'/>
</Tabs>
- props 与 Tabs props一致
- List props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | node | 可选 | ||
value | 适用于增加SelectableListHOC后。选中和当前value匹配的item | string | 必选 | |
onSelectedChange | 适用于增加SelectableListHOC后。选中项改变时触发.参数(value, item) | func | () => {} | 可选 |
- ListItem props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
primaryText | 文字 | string | 'list-item' | 可选 |
secondaryText | 右侧文字 | string | '' | 可选 |
leftIcon | 左侧图标 | number | '' | 可选 |
rightArrow | 右侧箭头 | element | '' | 可选 |
value | 适用于增加SelectableListHOC后。区分不同item唯一值 | string | 必选 | |
onClick | 列表点击行为.若为可选择的列表,参数({value);若为普通列表,参数(event) | func | () => {} | 可选 |
children | 自定义组件内容 | node | null | 可选 |
其他属性(eg: className等未在文档中声明的属性),也可加到当前元素上
当ListItem设置children,则primaryText, secondaryText失效
<List>
<ListItem primaryText="内容" secondaryText="其他内容"/>
...
</List>
<ListItem onClick={ () => {} }>
<div>
自定义内容
</div>
</ListItem>
- SortGroup props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | , , , 其中一个或多个的集合 | node | 是 | |
onSortInfoUpdate | 筛选条件变化后的回调,参数(sortInfo)当前的筛选条件 | func | () => {} | 可选 |
- SortLabel、SortList、SortToggle props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
filterItem | 筛选条件,具体格式如下说明 | array | [{label: '筛选',value: '1'}] | 是 |
onClick | 点击排序后的回调。参数:(当前选中的筛选条件, 选中状态) | func | () => {} | 可选 |
name | 唯一,sortGroup用来搜集当前选中的项 | string | 'sort_index' | 可选 |
filterItem说明:对于SortList可为函数,且返回promise,用于异步获取list
参数 | 说明 | 类型 |
---|---|---|
value | 筛选key值,唯一 | string |
label | 文本,即选择某项筛选条件后显示的名称 | string |
displayLabel | 文本,通常用于SortList下拉列表中选中某项后,最终展示的标题 | string |
isDefault | 是否默认选中.通常用于SortList | bool |
isAll | 点击该项时,不进行筛选.通常用于SortList | bool |
- SortMulti props
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
filterItem | 筛选条件 | array | [{title: '多选标题', items: [{label: xx, value: xx}]] | 是 |
onClick | 同上 | func | () => {} | 可选 |
name | 同上 | string | '' | 可选 |
const onSortInfoUpdate = (ret) => {
console.log(ret)
// {
// sort_0: {label: 'xx', value: '1'},
// sort_1: {xxxxx}
// }
}
<SortGroup onSortInfoUpdate={onSortInfoUpdate}>
<SortLabel filterItem={[{label: '筛选', value: '1'}]}/>
<SortList filterItem={
[
label: '条件1',
vlaue: '1',
isDefault: true
],
[
label: '条件2',
value: '2'
]
}/>
</SortGroup>
-
desc
给列表提供可选择的功能
-
params
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
config | 自定义选中项样式,可添加selectedClassName或selectedStyle, | obj | {selectedClassName: '', selectedStyle: {color: '#ff552e'}} | 可选 |
component | List | node | 必选 | |
children | ListItem | node | 必选 | |
value | 当前选中项,受控,需要在onSelectedChange中手动更新value | string | 必选 | |
initValue | 初始选中项 | string | 否 | |
onSelectedChange | 点击某项触发 | func | 必选 |
const SelectableList = SelectableListHOC({
selectedClassName: 'active'
})(List);
<SelectableList value='a' onSelectedChange={ (event, value, item) => {} }>
<ListItem value="a" onClick={ () => {} } >
<自定义内容/>
</ListItem>
<ListItem value="a" >
<自定义内容/>
</ListItem>
</SelectableList>
-
desc
功能操作弹层
-
params
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
showState | 状态, | bool | false | 必选 |
label | 操作说明 | node | 操作的说明或提示 | 必选 |
tip | 其他文字说明 | node | 可选 | |
onActionChange | 选中触发 | function | () => {} | 必选 |
list | 操作列表1 | array | [] | 必选 |
bottom | 操作列表2 | array | [] | 必选 |
const handleActionChange = (item) => {
// {label: 'xx', key: 'xxx'}
};
<ActionSheet
showState={ true }
list={ [
{
label: '确定',
key: 'ok',
},
{
label: '其他操作',
key: 'other',
}
]
}
bottom={ [{
label: '取消',
key: 'cancel'
}]
}
onActionChange={ handleActionChange }
className="choose-type-modal"
/>
-
desc
通知标签,一版般用在列表右侧,默认20x20圆形图标
-
params
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
content | 内容 | element | 可选 | |
style | 自定义样式 | obj | 可选 |
<NotifyLabel content={1} style={{color: 'red'}}/>
-
desc
跑马灯
-
params
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
width | 宽度 | number or string | 100% | 可选 |
height | 高度 | number | 200 | 可选 |
slideIndex | 当前所处焦点 | number | 0 | 可选 |
swipeSpeed | 切换命中比例 | number | 3 | 可选 |
speed | 切换时间 | number | 300 | 可选 |
easing | 动画曲线 | string | easeOutCirc(https://github.com/chenglou/tween-functions) | 可选 |
autoplay | 是否自动播放 | bool | false | 可选 |
autoplayInterval | 自动播放时间间隔 | number | 8000 | 可选 |
arrow | 下方圆点 | bool | true | 可选 |
page | 页码 | bool | false | 可选 |
beforeSlide | 滑动前函数 | fun | () => {} | 可选 |
beforeSlide | 滑动后函数 | fun | () => {} | 可选 |
<Carousel autoplay={true}>
<div className="test-page1">1</div>
<div className="test-page2">2</div>
<div className="test-page3">3</div>
<div className="test-page4">4</div>
</Carousel>
-
desc
slider 横向滚动
-
params
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
children | 子 | node | 无 | 可选 |
<Slider>
<div style={{width: 200, height: 150, backgroundColor: '#cccccc'}}></div>
<div style={{width: 200, height: 150, backgroundColor: 'pink'}}></div>
<div style={{width: 200, height: 150, backgroundColor: '#8a2be2'}}></div>
<div style={{width: 200, height: 150, backgroundColor: '#FF9912'}}></div>
</Slider>
-
desc
分割线,一般用于列表之间
-
params
参数 | 说明 | 类型 | 默认值 | 是否必要 |
---|---|---|---|---|
inset | 是否有14px的左右padding | boolean | false | 可选 |
style | 自定义样式 | obj | 可选 |
<List>
<ListItem />
<Divider />
<ListItem />
</List>