Skip to content

Commit 167d26b

Browse files
authored
feat: amis 渲染支持将 schema 的tagger标记到dom (#16180)
1 parent 2da7a7c commit 167d26b

File tree

78 files changed

+442
-78
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+442
-78
lines changed

examples/components/Form/Custom.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class MyFormItem extends React.Component {
2727
}
2828

2929
@Renderer({
30-
test: /(^|\/)my\-renderer$/,
30+
type: 'my-renderer',
3131
autoVar: true
3232
})
3333
class CustomRenderer extends React.Component {

examples/components/MdRenderer.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable no-unused-vars */
22
import React from 'react';
3-
import {findDOMNode} from 'react-dom';
3+
import {findDomCompat as findDOMNode} from 'amis-core';
44
import {createRoot} from 'react-dom/client';
55
import {getTheme, render} from 'amis';
66
import {LazyComponent} from 'amis-core';

packages/amis-core/src/RootRenderer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import pick from 'lodash/pick';
1111
import mapValues from 'lodash/mapValues';
1212
import {saveAs} from 'file-saver';
1313
import {normalizeApi} from './utils/api';
14-
import {findDOMNode} from 'react-dom';
14+
import {findDomCompat as findDOMNode} from './utils/findDomCompat';
1515
import LazyComponent from './components/LazyComponent';
1616
import {hasAsyncRenderers, loadAsyncRenderersByType} from './factory';
1717
import {dispatchEvent} from './utils/renderer-event';
18-
import {GlobalVariableItem} from 'amis-core';
18+
import {GlobalVariableItem} from './globalVar';
1919

2020
export interface RootRendererProps extends RootProps {
2121
/**

packages/amis-core/src/SchemaRenderer.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {observeGlobalVars} from './globalVar';
4646
import type {IRootStore} from './store/root';
4747
import {createObjectFromChain, extractObjectChain} from './utils';
4848
import {IIRendererStore} from './store/index';
49+
import TaggerWrapper from './TaggerWrapper';
4950

5051
interface SchemaRendererProps
5152
extends Partial<Omit<RendererProps, 'statusStore'>>,
@@ -656,6 +657,12 @@ export class SchemaRenderer extends React.Component<SchemaRendererProps, any> {
656657
);
657658
}
658659

660+
if (schema.$$tagger) {
661+
component = (
662+
<TaggerWrapper tagger={schema.$$tagger}>{component}</TaggerWrapper>
663+
);
664+
}
665+
659666
return this.props.env.enableAMISDebug ? (
660667
<DebugWrapper renderer={renderer}>{component}</DebugWrapper>
661668
) : (
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from 'react';
2+
import {findDomCompat} from './utils/findDomCompat';
3+
4+
interface TaggerWrapperProps {
5+
children: React.ReactElement;
6+
tagger: {
7+
[propName: string]: string | number;
8+
};
9+
}
10+
11+
/**
12+
* 自动给组件对应 dom 打标记,开发态时才会进来
13+
* @param param0
14+
* @returns
15+
*/
16+
export const TaggerWrapper: React.FC<TaggerWrapperProps> = ({
17+
children,
18+
tagger
19+
}) => {
20+
const ref = React.useRef<HTMLElement | null>(null);
21+
22+
React.useLayoutEffect(() => {
23+
if (!ref.current || !tagger) {
24+
return;
25+
}
26+
27+
const dom = findDomCompat(ref.current);
28+
const attrs: any = {};
29+
Object.keys(tagger).forEach(key => {
30+
if (typeof tagger[key] === 'string' || typeof tagger[key] === 'number') {
31+
attrs[`data-amis-tagger-${key}`] = String(tagger[key]);
32+
}
33+
});
34+
35+
Object.keys(attrs).forEach(key => {
36+
dom?.setAttribute(key, attrs[key]);
37+
});
38+
39+
return () => {
40+
Object.keys(attrs).forEach(key => {
41+
dom?.removeAttribute(key);
42+
});
43+
};
44+
}, [tagger, ref.current]);
45+
46+
// 合并 ref:保持原有 ref,同时添加我们的 ref
47+
const mergedRef = React.useCallback(
48+
(node: HTMLElement | null) => {
49+
ref.current = node;
50+
51+
// 如果原有 children 有 ref,也调用它
52+
const childRef = (children as any).ref;
53+
if (childRef) {
54+
if (typeof childRef === 'function') {
55+
childRef(node);
56+
} else {
57+
// ref 对象
58+
childRef.current = node;
59+
}
60+
}
61+
},
62+
[children]
63+
);
64+
65+
return React.cloneElement(children, {
66+
ref: mergedRef
67+
} as any);
68+
};
69+
70+
export default TaggerWrapper;

packages/amis-core/src/components/Overlay.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
import Portal from 'react-overlays/Portal';
88
import classNames from 'classnames';
9-
import ReactDOM, {findDOMNode} from 'react-dom';
9+
import ReactDOM from 'react-dom';
10+
import {findDomCompat as findDOMNode} from '../utils';
1011
import React, {cloneElement} from 'react';
1112
import {
1213
autobind,
@@ -134,7 +135,7 @@ class Position extends React.Component<any, any> {
134135
getTarget = () => {
135136
const {target} = this.props;
136137
const targetElement = typeof target === 'function' ? target() : target;
137-
return (targetElement && ReactDOM.findDOMNode(targetElement)) || null;
138+
return (targetElement && findDOMNode(targetElement)) || null;
138139
};
139140

140141
componentDidUpdate(prevProps: any) {

packages/amis-core/src/components/PopOver.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import React from 'react';
8-
import {findDOMNode} from 'react-dom';
8+
import {findDomCompat as findDOMNode} from '../utils/findDomCompat';
99
import {ClassNamesFn, themeable} from '../theme';
1010
import {autobind, camel, preventDefault, TestIdBuilder} from '../utils';
1111
import {SubPopoverDisplayedID} from './Overlay';

packages/amis-core/src/renderers/Item.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import {HocStoreFactory} from '../WithStore';
3838
import {wrapControl} from './wrapControl';
3939
import debounce from 'lodash/debounce';
4040
import {isApiOutdated, isEffectiveApi} from '../utils/api';
41-
import {findDOMNode} from 'react-dom';
41+
import {findDomCompat as findDOMNode} from '../utils/findDomCompat';
4242
import {
4343
createObjectFromChain,
4444
dataMapping,

packages/amis-core/src/utils/RootClose.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import React, {useState} from 'react';
66
import useRootClose from 'react-overlays/useRootClose';
7-
import {findDOMNode} from 'react-dom';
7+
import {findDomCompat as findDOMNode} from '../utils/findDomCompat';
88

99
export const RootClose = ({children, onRootClose, ...props}: any) => {
1010
const [rootComponent, attachRef] = useState(null);

packages/amis-core/src/utils/debug.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
import React, {Component, useEffect, useRef, useState, version} from 'react';
66
import cx from 'classnames';
7-
import {findDOMNode, render, unmountComponentAtNode} from 'react-dom';
7+
import {render, unmountComponentAtNode} from 'react-dom';
8+
import {findDomCompat as findDOMNode} from './findDomCompat';
89
// import {createRoot} from 'react-dom/client';
910
import {autorun, observable, action} from 'mobx';
1011
import {observer} from 'mobx-react';

0 commit comments

Comments
 (0)