From b875d023217dfea1c9d05740e9e4d3e449156ecf Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 16 Jun 2021 18:25:09 +0800 Subject: [PATCH] =?UTF-8?q?default=20value=20=E5=92=8C=20=20value=20?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SchemaRenderer.tsx | 5 +++- src/renderers/Audio.tsx | 45 ++++++++++++++++------------------ src/renderers/Carousel.tsx | 21 ++++------------ src/renderers/Color.tsx | 14 +++-------- src/renderers/Date.tsx | 4 +++- src/renderers/Each.tsx | 25 ++++++++++--------- src/renderers/Image.tsx | 8 ++----- src/renderers/Images.tsx | 6 ++--- src/renderers/Json.tsx | 5 ++-- src/renderers/Link.tsx | 3 ++- src/renderers/Mapping.tsx | 5 ++-- src/renderers/Markdown.tsx | 6 +++-- src/renderers/Plain.tsx | 3 ++- src/renderers/Progress.tsx | 3 ++- src/renderers/QRCode.tsx | 3 ++- src/renderers/SearchBox.tsx | 11 ++++++--- src/renderers/SparkLine.tsx | 6 ++--- src/renderers/Status.tsx | 3 ++- src/renderers/Steps.tsx | 4 +++- src/renderers/Tpl.tsx | 5 ++-- src/utils/helper.ts | 48 ++++++++++++++++++++++++++++++++++++- 21 files changed, 134 insertions(+), 99 deletions(-) diff --git a/src/SchemaRenderer.tsx b/src/SchemaRenderer.tsx index 322a1508f..4d4a92435 100644 --- a/src/SchemaRenderer.tsx +++ b/src/SchemaRenderer.tsx @@ -36,6 +36,8 @@ const defaultOmitList = [ 'disabledOn', 'component', 'detectField', + 'defaultValue', + 'defaultData', 'required', 'requiredOn', 'syncSuperStore' @@ -234,7 +236,7 @@ export class SchemaRenderer extends React.Component { const renderer = this.renderer as RendererConfig; schema = filterSchema(schema, renderer, rest); - const {data: defaultData, ...restSchema} = schema; + const {data: defaultData, value: deafultValue, ...restSchema} = schema; const Component = renderer.component; return ( @@ -243,6 +245,7 @@ export class SchemaRenderer extends React.Component { {...restSchema} {...chainEvents(rest, restSchema)} defaultData={defaultData} + deafultValue={deafultValue} $path={$path} $schema={schema} ref={this.refFn} diff --git a/src/renderers/Audio.tsx b/src/renderers/Audio.tsx index 89d6c602c..1a4edb70a 100644 --- a/src/renderers/Audio.tsx +++ b/src/renderers/Audio.tsx @@ -1,7 +1,7 @@ import React from 'react'; import upperFirst from 'lodash/upperFirst'; import {Renderer, RendererProps} from '../factory'; -import {autobind} from '../utils/helper'; +import {autobind, detectPropValueChanged, getPropValue} from '../utils/helper'; import {Icon} from '../components/icons'; import {resolveVariable} from '../utils/tpl-builtin'; import {filter} from '../utils/tpl'; @@ -93,12 +93,9 @@ export class Audio extends React.Component { state: AudioState = { src: - this.props.value || - (this.props.src - ? filter(this.props.src, this.props.data, '| raw') - : '') || - resolveVariable(this.props.name, this.props.data) || - '', + getPropValue(this.props, props => + props.src ? filter(props.src, props.data, '| raw') : undefined + ) || '', isReady: false, muted: false, playing: false, @@ -131,24 +128,22 @@ export class Audio extends React.Component { componentWillReceiveProps(nextProps: AudioProps) { const props = this.props; - if ( - props.value !== nextProps.value || - filter(props.src as string, props.data, '| raw') !== - filter(nextProps.src as string, nextProps.data, '| raw') - ) { - this.setState( - { - src: - nextProps.value || - filter(nextProps.src as string, nextProps.data, '| raw'), - playing: false - }, - () => { - this.audio.load(); - this.progress(); - } - ); - } + detectPropValueChanged( + nextProps, + props, + value => + this.setState( + { + src: value, + playing: false + }, + () => { + this.audio.load(); + this.progress(); + } + ), + props => (props.src ? filter(props.src, props.data, '| raw') : undefined) + ); } @autobind diff --git a/src/renderers/Carousel.tsx b/src/renderers/Carousel.tsx index a1b62a113..2cf48d6fe 100644 --- a/src/renderers/Carousel.tsx +++ b/src/renderers/Carousel.tsx @@ -10,7 +10,8 @@ import { autobind, createObject, isObject, - isArrayChildrenModified + isArrayChildrenModified, + getPropValue } from '../utils/helper'; import {Icon} from '../components/icons'; import {BaseSchema, SchemaCollection, SchemaName, SchemaTpl} from '../Schema'; @@ -147,11 +148,7 @@ export class Carousel extends React.Component { state = { current: 0, - options: - this.props.options || - this.props.value || - resolveVariable(this.props.name, this.props.data) || - [], + options: this.props.options || getPropValue(this.props) || [], nextAnimation: '' }; @@ -162,16 +159,8 @@ export class Carousel extends React.Component { componentDidUpdate(prevProps: CarouselProps) { const props = this.props; - const nextOptions = - props.options || - props.value || - resolveVariable(props.name, props.data) || - []; - const prevOptions = - prevProps.options || - prevProps.value || - resolveVariable(prevProps.name, prevProps.data) || - []; + const nextOptions = props.options || getPropValue(props); + const prevOptions = prevProps.options || getPropValue(prevProps) || []; if (isArrayChildrenModified(prevOptions, nextOptions)) { this.setState({ diff --git a/src/renderers/Color.tsx b/src/renderers/Color.tsx index 744b6f1d1..c8250ba9c 100644 --- a/src/renderers/Color.tsx +++ b/src/renderers/Color.tsx @@ -4,6 +4,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {BaseSchema} from '../Schema'; +import {getPropValue} from '../utils/helper'; import {resolveVariableAndFilter} from '../utils/tpl-builtin'; /** @@ -39,17 +40,8 @@ export class ColorField extends React.Component { }; render() { - const { - className, - data, - classnames: cx, - name, - value, - defaultColor, - showValue - } = this.props; - const color = - value || (name ? resolveVariableAndFilter(name, data, '| raw') : null); + const {className, classnames: cx, defaultColor, showValue} = this.props; + const color = getPropValue(this.props); return (
diff --git a/src/renderers/Date.tsx b/src/renderers/Date.tsx index 6a8c4a30b..d242269e7 100644 --- a/src/renderers/Date.tsx +++ b/src/renderers/Date.tsx @@ -2,6 +2,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import moment from 'moment'; import {BaseSchema} from '../Schema'; +import {getPropValue} from '../utils/helper'; /** * Date 展示渲染器。 @@ -90,7 +91,6 @@ export class DateField extends React.Component { render() { const { - value, valueFormat, format, placeholder, @@ -103,6 +103,8 @@ export class DateField extends React.Component { {placeholder} ); + const value = getPropValue(this.props); + if (value) { let ISODate = moment(value, moment.ISO_8601); let NormalDate = moment(value, valueFormat); diff --git a/src/renderers/Each.tsx b/src/renderers/Each.tsx index 398c8a859..889582336 100644 --- a/src/renderers/Each.tsx +++ b/src/renderers/Each.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {Schema} from '../types'; import {resolveVariable} from '../utils/tpl-builtin'; -import {createObject, isObject} from '../utils/helper'; +import {createObject, getPropValue, isObject} from '../utils/helper'; import {BaseSchema, SchemaCollection} from '../Schema'; /** @@ -43,24 +43,23 @@ export default class Each extends React.Component { name, className, render, - value, + defaultValue, items, placeholder, classnames: cx, translate: __ } = this.props; - const arr = - typeof value !== 'undefined' - ? isObject(value) - ? Object.keys(value).map(key => ({ - key: key, - value: value[key] - })) - : Array.isArray(value) - ? value - : [] - : resolveVariable(name, data); + const value = getPropValue(this.props); + + const arr = isObject(value) + ? Object.keys(value).map(key => ({ + key: key, + value: value[key] + })) + : Array.isArray(value) + ? value + : []; return (
diff --git a/src/renderers/Image.tsx b/src/renderers/Image.tsx index a07655b86..04db3f650 100644 --- a/src/renderers/Image.tsx +++ b/src/renderers/Image.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {filter} from '../utils/tpl'; import {ClassNamesFn, themeable, ThemeProps} from '../theme'; -import {autobind} from '../utils/helper'; +import {autobind, getPropValue} from '../utils/helper'; import {Icon} from '../components/icons'; import {LocaleProps, localeable} from '../locale'; import {BaseSchema, SchemaClassName, SchemaTpl, SchemaUrlPath} from '../Schema'; @@ -282,11 +282,7 @@ export class ImageField extends React.Component { const finnalSrc = src ? filter(src, data, '| raw') : ''; let value = - finnalSrc || - this.props.value || - resolveVariable(name, data) || - defaultImage || - imagePlaceholder; + finnalSrc || getPropValue(this.props) || defaultImage || imagePlaceholder; return (
diff --git a/src/renderers/Images.tsx b/src/renderers/Images.tsx index d9cbeb363..90e0f1c64 100644 --- a/src/renderers/Images.tsx +++ b/src/renderers/Images.tsx @@ -7,7 +7,7 @@ import { resolveVariableAndFilter } from '../utils/tpl-builtin'; import Image, {ImageThumbProps, imagePlaceholder} from './Image'; -import {autobind} from '../utils/helper'; +import {autobind, getPropValue} from '../utils/helper'; import {BaseSchema, SchemaClassName, SchemaUrlPath} from '../Schema'; /** @@ -166,12 +166,12 @@ export class ImagesField extends React.Component { options } = this.props; - let value = this.props.value ?? resolveVariable(name, data); + let value: any; let list: any; if (typeof source === 'string' && isPureVariable(source)) { list = resolveVariableAndFilter(source, data, '| raw') || undefined; - } else if (Array.isArray(value)) { + } else if (Array.isArray((value = getPropValue(this.props)))) { list = value; } else if (Array.isArray(options)) { list = options; diff --git a/src/renderers/Json.tsx b/src/renderers/Json.tsx index 558389d80..0ea0d8936 100644 --- a/src/renderers/Json.tsx +++ b/src/renderers/Json.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import JSONTree from 'react-json-tree'; -import {autobind} from '../utils/helper'; +import {autobind, getPropValue} from '../utils/helper'; import {BaseSchema} from '../Schema'; import {resolveVariableAndFilter, isPureVariable} from '../utils/tpl-builtin'; /** @@ -152,7 +152,6 @@ export class JSONField extends React.Component { render() { const { className, - value, jsonTheme, classnames: cx, hideRoot, @@ -160,6 +159,8 @@ export class JSONField extends React.Component { source } = this.props; + const value = getPropValue(this.props); + let data = value; if (source !== undefined && isPureVariable(source)) { data = resolveVariableAndFilter(source, this.props.data, '| raw'); diff --git a/src/renderers/Link.tsx b/src/renderers/Link.tsx index 0f004c261..1047eaf45 100644 --- a/src/renderers/Link.tsx +++ b/src/renderers/Link.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {BaseSchema, SchemaTpl} from '../Schema'; +import {getPropValue} from '../utils/helper'; import {filter} from '../utils/tpl'; /** @@ -48,7 +49,7 @@ export class LinkField extends React.Component { title } = this.props; - let value = this.props.value; + let value = getPropValue(this.props); const finnalHref = href ? filter(href, data, '| raw') : ''; return ( diff --git a/src/renderers/Mapping.tsx b/src/renderers/Mapping.tsx index 5adf8560c..f7ab6e6f9 100644 --- a/src/renderers/Mapping.tsx +++ b/src/renderers/Mapping.tsx @@ -12,7 +12,7 @@ import { } from '../Schema'; import {withStore} from '../components/WithStore'; import {flow, Instance, types} from 'mobx-state-tree'; -import {getVariable, guid, isObject} from '../utils/helper'; +import {getPropValue, getVariable, guid, isObject} from '../utils/helper'; import {StoreNode} from '../store/node'; import isPlainObject from 'lodash/isPlainObject'; import {isPureVariable, resolveVariableAndFilter} from '../utils/tpl-builtin'; @@ -187,8 +187,7 @@ export const MappingField = withStore(props => } = this.props; const map = store.map; - let key = - this.props.value ?? (name ? getVariable(data, name) : undefined); + let key = getPropValue(this.props); let viewValue: React.ReactNode = ( {placeholder} diff --git a/src/renderers/Markdown.tsx b/src/renderers/Markdown.tsx index 895cdd512..5a77e37e3 100644 --- a/src/renderers/Markdown.tsx +++ b/src/renderers/Markdown.tsx @@ -6,6 +6,7 @@ import {Renderer, RendererProps} from '../factory'; import {BaseSchema} from '../Schema'; import {resolveVariableAndFilter} from '../utils/tpl-builtin'; import LazyComponent from '../components/LazyComponent'; +import {getPropValue} from '../utils/helper'; /** * Markdown 渲染 @@ -43,9 +44,10 @@ export interface MarkdownProps export class Markdown extends React.Component { render() { - const {className, data, classnames: cx, name, value} = this.props; + const {className, data, classnames: cx, name} = this.props; const content = - value || (name ? resolveVariableAndFilter(name, data, '| raw') : null); + getPropValue(this.props) || + (name ? resolveVariableAndFilter(name, data, '| raw') : null); return (
diff --git a/src/renderers/Plain.tsx b/src/renderers/Plain.tsx index a219434dc..bd0a86515 100644 --- a/src/renderers/Plain.tsx +++ b/src/renderers/Plain.tsx @@ -3,6 +3,7 @@ import {Renderer, RendererProps} from '../factory'; import {filter} from '../utils/tpl'; import cx from 'classnames'; import {BaseSchema, SchemaTpl} from '../Schema'; +import {getPropValue} from '../utils/helper'; /** * Plain 纯文本渲染器 @@ -47,7 +48,6 @@ export class Plain extends React.Component { const { className, wrapperComponent, - value, text, data, tpl, @@ -56,6 +56,7 @@ export class Plain extends React.Component { classnames: cx } = this.props; + const value = getPropValue(this.props); const Component = wrapperComponent || (inline ? 'span' : 'div'); return ( diff --git a/src/renderers/Progress.tsx b/src/renderers/Progress.tsx index 037b5e81b..c55303fc3 100644 --- a/src/renderers/Progress.tsx +++ b/src/renderers/Progress.tsx @@ -5,6 +5,7 @@ import {Api, SchemaNode, PlainObject} from '../types'; import {filter} from '../utils/tpl'; import cx from 'classnames'; import {BaseSchema, SchemaClassName} from '../Schema'; +import {getPropValue} from '../utils/helper'; /** * 进度展示控件。 @@ -91,7 +92,7 @@ export class ProgressField extends React.Component { classnames: cx } = this.props; - let value = this.props.value; + let value = getPropValue(this.props); let viewValue: React.ReactNode = ( {placeholder} ); diff --git a/src/renderers/QRCode.tsx b/src/renderers/QRCode.tsx index 32ed7bcf2..c32704863 100644 --- a/src/renderers/QRCode.tsx +++ b/src/renderers/QRCode.tsx @@ -75,11 +75,12 @@ export default class QRCode extends React.Component { placeholder, level, value, + defaultValue, data, classPrefix: ns } = this.props; - const finalValue = filter(value, data, '| raw'); + const finalValue = value || filter(defaultValue, data, '| raw'); return (
diff --git a/src/renderers/SearchBox.tsx b/src/renderers/SearchBox.tsx index b59eb6a7b..be6557362 100644 --- a/src/renderers/SearchBox.tsx +++ b/src/renderers/SearchBox.tsx @@ -3,7 +3,12 @@ import {Renderer, RendererProps} from '../factory'; import React from 'react'; import {BaseSchema, SchemaClassName} from '../Schema'; import SearchBox from '../components/SearchBox'; -import {autobind, getVariable, setVariable} from '../utils/helper'; +import { + autobind, + getPropValue, + getVariable, + setVariable +} from '../utils/helper'; /** * 搜索框渲染器 @@ -67,7 +72,7 @@ export class SearchBoxRenderer extends React.Component { handleCancel() { const name = this.props.name; const onQuery = this.props.onQuery; - const value = this.props.value ?? getVariable(this.props.data, name); + const value = getPropValue(this.props); if (value !== '') { const data: any = {}; setVariable(data, name, ''); @@ -95,7 +100,7 @@ export class SearchBoxRenderer extends React.Component { className } = this.props; - const value = this.props.value ?? getVariable(data, name); + const value = getPropValue(this.props); return ( { render() { const {value, name, data, clickAction} = this.props; - - const finalValue = - value ?? (name ? resolveVariableAndFilter(name, data) : [1, 1]); + const finalValue = getPropValue(this.props) || [1, 1]; return ( { classnames: cx, data } = this.props; - let value = this.props.value; + let value = getPropValue(this.props); let viewValue: React.ReactNode = ( {placeholder} ); diff --git a/src/renderers/Steps.tsx b/src/renderers/Steps.tsx index ed86aab50..8f7be2f66 100644 --- a/src/renderers/Steps.tsx +++ b/src/renderers/Steps.tsx @@ -8,6 +8,7 @@ import { } from '../components/WithRemoteConfig'; import {resolveVariable} from '../utils/tpl-builtin'; import {filter} from '../utils/tpl'; +import {getPropValue} from '../utils/helper'; enum StepStatus { wait = 'wait', @@ -87,7 +88,6 @@ export function Steps(props: StepsProps) { className, classnames: cx, steps, - value = 0, status, data, source, @@ -98,6 +98,8 @@ export function Steps(props: StepsProps) { config || steps || []; + + const value = getPropValue(props) ?? 0; const resolveValue = typeof value === 'string' && isNaN(+value) ? (resolveVariable(value, data) as string) || +value diff --git a/src/renderers/Tpl.tsx b/src/renderers/Tpl.tsx index 3a53653a1..e3df0370d 100644 --- a/src/renderers/Tpl.tsx +++ b/src/renderers/Tpl.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {filter} from '../utils/tpl'; import cx from 'classnames'; -import {anyChanged} from '../utils/helper'; +import {anyChanged, getPropValue} from '../utils/helper'; import {escapeHtml} from '../utils/tpl-builtin'; import {BaseSchema, SchemaTpl} from '../Schema'; @@ -74,7 +74,8 @@ export class Tpl extends React.Component { } getContent() { - const {tpl, html, text, raw, value, data, placeholder} = this.props; + const {tpl, html, text, raw, data, placeholder} = this.props; + const value = getPropValue(this.props); if (raw) { return raw; diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 39f1a9334..25f50dd66 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -150,7 +150,7 @@ export function findIndex( export function getVariable( data: {[propName: string]: any}, - key: string, + key: string | undefined, canAccessSuper: boolean = true ): any { if (!data || !key) { @@ -1528,3 +1528,49 @@ export function getScrollbarWidth() { return scrollbarWidth; } + +// 统一的获取 value 值方法 +export function getPropValue< + T extends { + value?: any; + name?: string; + data?: any; + defaultValue?: any; + } +>(props: T, getter?: (props: T) => any) { + const {name, value, data, defaultValue} = props; + return value ?? getter?.(props) ?? getVariable(data, name) ?? defaultValue; +} + +// 检测 value 是否有变化,有变化就执行 onChange +export function detectPropValueChanged< + T extends { + value?: any; + name?: string; + data?: any; + defaultValue?: any; + } +>( + props: T, + prevProps: T, + onChange: (value: any) => void, + getter?: (props: T) => any +) { + let nextValue: any; + if (props.value !== prevProps.value) { + onChange(props.value); + } else if ( + (nextValue = getter?.(props)) !== undefined && + nextValue !== getter!(prevProps) + ) { + onChange(nextValue); + } else if ( + typeof props.name === 'string' && + (nextValue = getVariable(props.data, props.name)) !== undefined && + nextValue !== getVariable(prevProps.data, prevProps.name) + ) { + onChange(nextValue); + } else if (props.defaultValue !== prevProps.defaultValue) { + onChange(props.defaultValue); + } +}