UNPKG

hc-components

Version:

基于react的通用组件库

164 lines (148 loc) 4.31 kB
import React from 'react'; import PropTypes from 'prop-types'; export class DataSet extends React.PureComponent { static formatter = {}; static themeOptions = {}; static theme = (themeOptions) => { DataSet.themeOptions = themeOptions; } static propTypes = { Component: PropTypes.any, childProps: PropTypes.object, onChange: PropTypes.object, value: PropTypes.any, data: PropTypes.object, getResolver: PropTypes.func, defaultValue: PropTypes.string, format: PropTypes.string, formatter: PropTypes.func, children: PropTypes.any, spin: PropTypes.bool, } static defaultProps = { data: {}, childProps: {} } constructor(props, context) { super(props, context); this.state = { pending: props.spin }; this.stateUpdater = {}; if (props.getResolver) { this._resolver = props.getResolver(props.defaultValue); } /** * prop = { * value: Object | Function, * format: String, * formatter: Function, * setter: String | Function * } */ Object .keys(props.data) .forEach(name => { const prop = props.data[name]; if (prop.value) { const originValue = typeof prop.value === 'function' ? prop.value.call(this, this.props) : prop.value; const formatter = this.getFormatter(props.formatter, name); // formatter是一系列解决组件schema的格式化函数 if (formatter) { this.state[name] = formatter.call(this, prop.schema, originValue); } else { this.state[name] = originValue; } } if (prop.setter) { const setter = props.childProps[prop.setter]; this.stateUpdater[prop.setter] = (updateFn) => (this.setState((prevState) => { let newValue = typeof updateFn === 'function' ? updateFn.call(this, prevState[name]) : updateFn; const formatter = this.getFormatter(props.formatter, name); if (formatter) { newValue = formatter.call(this, prop.schema, newValue); } setter && setter(newValue); return {[name]: newValue}; })); } }); } componentDidMount() { this._resolver && this._resolver.then(iState => { iState.pending = false; this.setState(iState, this.props.onChange); }); } handleResolve = (value, params) => { if (this.props.spin) { this.setState({ pending: true }); } if (this.props.getResolver) { const resolver = this.props.getResolver(value, params); resolver.then(iState => { iState.pending = false; this.setState(iState, this.props.onChange); }); } } getFormatter(formatter, name) { if (!formatter && DataSet.formatter) { const comFormatter = DataSet.formatter[this.props.format] || {}; formatter = comFormatter[name]; } return formatter; } getRealInstance() { return this._instance; } render() { let option = {}; const {children, Component, childProps} = this.props; let type; if (Component) { type = Component.name; if (type && DataSet.themeOptions[type]) { option = DataSet.themeOptions[type]; } if (children) { return ( <Component ref={instance => this._instance = instance} {...option} {...childProps} {...this.state} {...this.stateUpdater}>{children}</Component> ); } else { return (<Component ref={instance => this._instance = instance} {...option} {...childProps} {...this.state} {...this.stateUpdater} />); } } else { type = children.type.name; if (type && DataSet.themeOptions[type]) { option = DataSet.themeOptions[type]; } return React.cloneElement(React.Children.only(children), { ref: instance => { this._instance = instance; if (typeof children.ref === 'function') { children.ref(instance); } }, ...option, ...childProps, ...this.state, ...this.stateUpdater }); } } }