hc-components-test
Version:
基于react的通用组件库
150 lines (135 loc) • 4.07 kB
JSX
import React from 'react';
import PropTypes from 'prop-types';
import localeContext from '../../localeContext';
export class DataSet extends React.PureComponent {
static formatter = {};
static themeOptions = {};
static theme = (themeOptions) => {
DataSet.themeOptions = themeOptions;
}
static propTypes = {
type: PropTypes.string,
component: PropTypes.element,
data: PropTypes.object,
actions: PropTypes.object,
ajax: PropTypes.object,
getResolver: PropTypes.func,
defaultValue: PropTypes.string,
format: PropTypes.string,
formatter: PropTypes.func,
children: PropTypes.any
}
static defaultProps = {
data: {}
}
constructor(props, context) {
super(props, context);
this.state = {};
this.stateUpdater = {};
this._ajax = props.ajax;
if (props.getResolver) {
const resolver = props.getResolver(props.defaultValue);
resolver.then(iState => {
this.setState(iState);
});
}
/**
* prop = {
* value: Object | Function,
* format: String,
* formatter: Function,
* setter: String | Function
* }
*/
Object
.keys(props.data)
.forEach(name => {
const prop = props.data[name];
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) {
this.stateUpdater[prop.setter] = (updateFn, callback) => (this.setState(({stateName}) => () => {
let newValue = typeof updateFn === 'function' ?
updateFn.call(this, stateName) :
updateFn;
const formatter = this.getFormatter(props.formatter, name);
if (formatter) {
newValue = formatter.call(this, prop.schema, newValue);
}
return newValue;
}, callback));
}
});
}
handleResolve = (value, params) => {
if (this.props.getResolver) {
const resolver = this.props.getResolver(value, params);
resolver.then(iState => {
this.setState(iState);
});
}
}
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 = {};
let type;
if (this.props.component) {
type = this.props.component.name;
if (type && DataSet.themeOptions[type]) {
option = DataSet.themeOptions[type];
}
if (this.props.children) {
return (
<this.props.component
ref={instance => this._instance = instance}
{...option}
{...this.props}
{...this.state}
{...this.stateUpdater}>{this.props.children}</this.props.component>
);
} else {
return (<this.props.component
ref={instance => this._instance = instance}
{...option}
{...this.props}
{...this.state}
{...this.stateUpdater} />);
}
} else {
type = this.props.children.type.name;
if (type && DataSet.themeOptions[type]) {
option = DataSet.themeOptions[type];
}
return React.cloneElement(React.Children.only(this.props.children), {
ref: instance => {
this._instance = instance;
if (typeof this.props.children.ref === 'function') {
this.props.children.ref(instance);
}
},
...option,
...this.props,
...this.state,
...this.stateUpdater
});
}
}
}