介绍三个React组件
简单介绍三个React组件吧。
- Image
- Table
- Form
React-Image
一个用于加载/预览图片的组件
Image
- 自动管理图片的
loading
和error
状态, 并显示不同提示. - 通过
IntersectionObserver
来实现图片懒加载 - 默认使用
Preview
来进行图片预览 - 可以通过
group
来管理图片预览列表, 同一个group
的图片会出现在预览列表中
import { Image } from '@zzwing/react-image'
;<Image src='any.jpg' width='200px' height='200px' onClick={this.onClick} />
Preview
图片浏览器, 可以放大/移动/切换等. 已集成到Image
中, 可以通过preview={false}
关闭预览功能. 也可以直接通过api
调用
import { PreviewApi } from '@zzwing/react-image'
const list = ['1.jpg', '2.jpg', '3.jpg']
// use index
PreviewApi.preview(2, list)
// or use src
PreviewApi.preview('2.jpg', list)
React-Table
可固定表头及两侧的表格.
antd的表格
antd
的表格也能满足该功能, 但也有几个不足点(我个人觉得)
- 要求每一列都要写入
width
用来固定列宽: 通过拆分thead
和tbody
来固定表头, 通过colgroup
来完成列宽的固定 - 表格高度不能自适应(有可能我使用方式不对?)
- 还有一点就是
antd
的表格功能太强大, 有很多功能我是用不上, 无形中增加了代码.
解决方法
指定表格的scrollTarget
, 既滚动
的目标, 默认是document.scrollingElement
.
- 当表头滚动到顶部时, 使用
transform
固定,由于属于同一个table
, 这样能解决tbody
和thead
不对齐的问题. - 固定两侧是通过
table
冗余实现(antd也是如此), 但只会冗余需要固定的部分。通过absolute
+padding
实现两侧固定. - 最后通过不同表格的同一行中的最大高度, 来设定其他表格该行的高度, 来达到高度同步
- 由于表格高度超过容器高度, 横向滚动条会被'隐藏', 因此提供了一个
scroller
来模拟横向滚动条, 也就是说任何时候都可以拉动滚动条. (当然也可以通过shift
+ 滚轮完成滚动)
不足点
- 由于
thead
使用了transform
, 因此也带来了几个问题- 当
thead
设了transform
之后,border
会失效, 因此使用了box-shadow
来模拟border
. 当然,
- 当
- 监听
mousewheel
来设置transform
的时候, 因为滚动和视图更新有延迟, 在firfox
和safari
会有抖动, 在chrome
下表现良好.- 在
chrome
和firfox
分别加入window.addEventListener('scroll', console.log)
, 鼠标滚动一次, 会发现ff
下会触发多次回调, 而chrome
只会触发一次
- 在
safari
下,thead
在被固定后的box-shadow
会失效.
使用方式
和antd
类似
import { Table } from '@zzwing/react-table'
const data = [{key1: '123', keyn: '123'}]
const columns = [{
title: 'column1',
fixed: 'left',
dataIndex: 'key1'
}, { /* ... */} , {
title: 'column2',
fixed: 'right',
dataIndex: 'keyn'
}]
<Table dataSource={data} columns={columns} rowKey='key1'/>
React-Form-Wrapper
封装了onChange
和value
的高阶组件, 与antd
的form
组件类似 不过只包含最基础的数据绑定, 也可通过options
来自定义数据的读写.
import FormWrapperHoc from '@zzwing/react-form-wrapper'
class Test extends React.PureComponent {
render() {
const { itemWrapper, getState } = this.props.formWrapper
const Input = itemWrapper('valueKey', {/* options */})(<input />)
const value = getState().valueKey
return (
<>
{Input}
you can get value for {value}
</>
)
}
}
链式key的读写实现
const Input = itemWrapper('a.b.c.d')(<input />)
按照一般实现, 会通过遍历每一层来set
/get
数据.
const _state = {}
const pathArr = path.split('.')
let tmp = _state
pathArr.forEach((each, index) => {
if(index === pathArr.length - 1) {
// do something
}
if(each in tmp) {
tmp = tmp[each]
} else {
tmp[each] = {}
tmp = tmp[each]
}
})
最近改了一种实现方法, 通过一个chain
对象直接存储path
对应的数据
// a.b.c.d
const chain = {
a: { b: chain['a.b'] },
'a.b': { c: chain['a.b.c'] },
'a.b.c': { d: chain['a.b.c.d'] },
'a.b.c.d': undefined
}
- 对于
get
操作, 则可以直接从chain[path]
中获取数据 - 对于
set
操作, 则可以直接修改chain['a.b.c'].d = 'str'
, 最后修改chain['a.b.c.d'] = 'str
- 因为修改的是同一个引用, 所以
set
操作会同步chain.a
和chain.a.b
最后
antd
是一个功能很全的UI库 但又正因为它功能很全,而大部分我是不需要,无形中可能添加了不少的代码量 所以我更喜欢是参考antd
的实现,去开发满足个人需求的组件 自己开发的组件,自己会更清楚,使用起来更加顺手,扩展起来也会很方便 不过对于DatePicker
这类组件,我想我还是直接用antd
的吧
希望这几个组件能帮到你.