diff --git a/docs/zh-CN/extend/custom-react.md b/docs/zh-CN/extend/custom-react.md index b37d9be25..96cf65836 100644 --- a/docs/zh-CN/extend/custom-react.md +++ b/docs/zh-CN/extend/custom-react.md @@ -58,7 +58,8 @@ import * as React from 'react'; import {Renderer} from 'amis'; @Renderer({ - type: 'my-renderer' + type: 'my-renderer', + autoVar: true // amis 1.8 之后新增的功能,自动解析出参数里的变量 }) class CustomRenderer extends React.Component { render() { @@ -72,7 +73,8 @@ class CustomRenderer extends React.Component { ```javascript Renderer({ - type: 'my-renderer' + type: 'my-renderer', + autoVar: true })(CustomRenderer); ``` @@ -148,6 +150,26 @@ class CustomRenderer extends React.Component { - `node` 子节点。 - `props` 可选,可以通过此对象跟子节点通信等。 +### 属性支持变量 + +> 1.8.0 及以上版本新增配置,之前版本需要调用 amis 里的 resolveVariableAndFilter 方法 + +前面的例子中组件参数都是静态的,但因为配置了 `autoVar: true`,使得所有组件参数将自动支持变量,比如下面例子中的 `tip` 在组件内拿到的将是解析后的值 + +```json +{ + "type": "page", + "data": { + "myVar": "var" + }, + "title": "自定义组件示例", + "body": { + "type": "my-renderer", + "tip": "${myVar}" + } +} +``` + ### 表单项的扩展 以上是普通渲染器的注册方式,如果是表单项,为了更简单的扩充,请使用 `FormItem` 注解,而不是 `Renderer`。 原因是如果用 `FormItem` 是不用关心:label 怎么摆,表单验证器怎么实现,如何适配表单的 3 种展现方式(水平、上下和内联模式),而只用关心:有了值后如何回显,响应用户交互设置新值。 diff --git a/examples/components/Form/Custom.jsx b/examples/components/Form/Custom.jsx index f58bbad2a..da96bd95a 100644 --- a/examples/components/Form/Custom.jsx +++ b/examples/components/Form/Custom.jsx @@ -26,13 +26,16 @@ class MyFormItem extends React.Component { } @Renderer({ - test: /(^|\/)my\-renderer$/ + test: /(^|\/)my\-renderer$/, + autoVar: true }) class CustomRenderer extends React.Component { render() { - const {tip} = this.props; - return ( -
{tip || '非 FormItem 类型的渲染器注册, 这种不能修改 form'}
+ const {tip, source} = this.props; + return source ? ( +
{`非 FormItem 类型的渲染器注册,通过变量获取 x 的值为:${source}`}
+ ) : ( +
{tip}
); } } @@ -121,7 +124,8 @@ export default { { type: 'control', body: { - type: 'my-renderer' + type: 'my-renderer', + source: '${x}' } }, @@ -222,7 +226,7 @@ export default { { type: 'my-renderer', - tip: '他能放 controls 里面,也能放外面。' + tip: '放表单外的情况' } ] }; diff --git a/src/SchemaRenderer.tsx b/src/SchemaRenderer.tsx index b447915fb..629cd0dce 100644 --- a/src/SchemaRenderer.tsx +++ b/src/SchemaRenderer.tsx @@ -23,6 +23,7 @@ import {SimpleMap} from './utils/SimpleMap'; import type {RendererEvent} from './utils/renderer-event'; import {observer} from 'mobx-react'; import {isAlive} from 'mobx-state-tree'; +import {isPureVariable, resolveVariableAndFilter} from './utils/tpl-builtin'; interface SchemaRendererProps extends Partial { schema: Schema; @@ -102,7 +103,7 @@ class BroadcastCmpt extends React.Component { } render() { - const {component: Component, rootStore, ...rest} = this.props; + const {component: Component, rootStore, autoVar, ...rest} = this.props; const visible = isAlive(rootStore) ? rootStore.visibleState[rest.$schema.id || rest.$path] : true; @@ -114,19 +115,33 @@ class BroadcastCmpt extends React.Component { if (disable) { (rest as any).disabled = true; } + const props = {...rest}; + + // 自动解析变量模式,主要是方便直接引入第三方组件库,无需为了支持变量封装一层 + if (autoVar) { + for (const key of Object.keys(rest.$schema)) { + if (typeof props[key] === 'string') { + props[key] = resolveVariableAndFilter( + props[key], + props.data, + '| raw' + ); + } + } + } // 函数组件不支持 ref https://reactjs.org/docs/refs-and-the-dom.html#refs-and-function-components return visible !== false ? ( isClassComponent ? ( ) : ( @@ -414,6 +429,7 @@ export class SchemaRenderer extends React.Component { ref={this.refFn} render={this.renderChild} component={Component} + autoVar={renderer.autoVar} /> ); diff --git a/src/factory.tsx b/src/factory.tsx index e5adaf78e..15d0bf2f9 100644 --- a/src/factory.tsx +++ b/src/factory.tsx @@ -70,6 +70,7 @@ export interface RendererBasicConfig { weight?: number; // 权重,值越低越优先命中。 isolateScope?: boolean; isFormItem?: boolean; + autoVar?: boolean; // 自动解析变量 // [propName:string]:any; }