feat: 渲染器支持自动解析参数变量 (#3912)

* feat: 渲染器支持自动解析参数变量

* 改成只要是字符串就处理
This commit is contained in:
吴多益 2022-03-31 14:33:07 +08:00 committed by GitHub
parent 9bb6e64efc
commit 430f5a1366
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 11 deletions

View File

@ -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 种展现方式(水平、上下和内联模式),而只用关心:有了值后如何回显,响应用户交互设置新值。

View File

@ -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 (
<div>{tip || '非 FormItem 类型的渲染器注册, 这种不能修改 form'}</div>
const {tip, source} = this.props;
return source ? (
<div>{`非 FormItem 类型的渲染器注册,通过变量获取 x 的值为:${source}`}</div>
) : (
<div>{tip}</div>
);
}
}
@ -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: '放表单外的情况'
}
]
};

View File

@ -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<RendererProps> {
schema: Schema;
@ -102,7 +103,7 @@ class BroadcastCmpt extends React.Component<BroadcastCmptProps> {
}
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<BroadcastCmptProps> {
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 ? (
<Component
ref={this.childRef}
{...rest}
{...props}
rootStore={rootStore}
dispatchEvent={this.dispatchEvent}
/>
) : (
<Component
{...rest}
{...props}
rootStore={rootStore}
dispatchEvent={this.dispatchEvent}
/>
@ -414,6 +429,7 @@ export class SchemaRenderer extends React.Component<SchemaRendererProps, any> {
ref={this.refFn}
render={this.renderChild}
component={Component}
autoVar={renderer.autoVar}
/>
);

View File

@ -70,6 +70,7 @@ export interface RendererBasicConfig {
weight?: number; // 权重,值越低越优先命中。
isolateScope?: boolean;
isFormItem?: boolean;
autoVar?: boolean; // 自动解析变量
// [propName:string]:any;
}