рдХреНрдпрд╛ рдЖрдкрдХрд╛ рдлреАрдЪрд░ рдЕрдиреБрд░реЛрдз рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИ?
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдПрдХ HTML рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреЗ рднреАрддрд░ рдбреНрд░реИрдЧ-рдПрдВрдб-рдбреНрд░реЙрдк рдХреЛ рд╕реАрдорд┐рдд рдХрд░рддреА рд╣реИред рдХрд┐рд╕реА рддрд░рд╣ рд╣рдореЗрдВ рдХреБрдЫ рдмрд╛рд╣рд░ iframe рдЕрдВрджрд░ рдЦреАрдВрдЪрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИред
рдЖрдк рдЬреЛ рд╕рдорд╛рдзрд╛рди рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЙрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ dnd HTML5backend рдмрд╕ рд╡рд┐рдВрдбреЛ рдореЗрдВ рдбреНрд░реИрдЧ рдХреЙрд▓рдмреИрдХ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИред рддреЛ рдЕрдЧрд░ рд╣рдо рдЖрдИрдлреНрд░реЗрдо рдХреЗ рдЕрдВрджрд░ рдШрдЯрдХреЛрдВ рдХреЛ рдХреЙрд▓рдмреИрдХ рдЯреНрд░рд┐рдЧрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдФрд░ React.createPortal
рдЖрдИрдлреНрд░реЗрдо рдХреЗ рдЕрдВрджрд░ рдШрдЯрдХреЛрдВ рдХреЛ рдмрд╛рд╣рд░ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдбреАрдПрдирдбреАрдкреНрд░реЛрд╡рд╛рдЗрдбрд░ рд╣реИред рдпрд╣ рд╕реМрднрд╛рдЧреНрдп рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЪрд┐рдВрддрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ рдЬрд┐рд╕ рдкрд░ рдореИрдВрдиреЗ рдзреНрдпрд╛рди рдирд╣реАрдВ рджрд┐рдпрд╛ред рдФрд░ рдХреЛрдб HTML5 рдмреИрдХрдПрдВрдб рдХреЗ рд╕рд╛рде рдЗрддрдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдирд╣реАрдВ рд╣реИред
import React, {
useRef,
useEffect,
useContext,
forwardRef,
} from 'react';
import classnames from 'classnames';
import { DndContext } from 'react-dnd';
// Frame base on createPortal inside iframe dom.
import Frame from 'react-frame-component';
const events = [
['dragstart', 'handleTopDragStart', false],
['dragstart', 'handleTopDragStartCapture', true],
['dragend', 'handleTopDragEndCapture', true],
['dragenter', 'handleTopDragEnter', false],
['dragenter', 'handleTopDragEnterCapture', true],
['dragleave', 'handleTopDragLeaveCapture', true],
['dragover', 'handleTopDragOver', false],
['dragover', 'handleTopDragOverCapture', true],
['drop', 'handleTopDrop', false],
['drop', 'handleTopDropCapture', true],
];
export const DndFrame = forwardRef((props = {}, ref) => {
const container = useRef(null);
const dndValue = useContext(DndContext) || {};
const { dragDropManager: { backend = {} } = {} } = dndValue;
const { children, className, containerProps = {}, ...others } = props;
const cls = classnames({
'dnd-frame': true,
[className]: !!className,
});
useEffect(() => {
const { current } = container;
if (!current) {
return;
}
// this make callback run in outside window
events.forEach((eventArgs = []) => {
const [name, callbackName, capture = false] = eventArgs;
const callback = backend[callbackName] && backend[callbackName].bind(backend);
current.addEventListener(name, (...args) => {
callback && callback(...args);
}, capture);
});
}, [container.current]);
return (
<Frame className={cls} ref={ref} {...others}>
<div className="dnd-frame-container" ref={container} {...containerProps}>
{ children }
</div>
</Frame>
);
});
рдЙрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ рдЬрд┐рди рдкрд░ рдЖрдкрдиреЗ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рд╣реИ
рдХреНрдпрд╛ рдЖрдк HTML5Backend рдХреЗ рд╕рд╛рде рдХреБрдЫ рд╡рд┐рдХрд▓реНрдк рдирд┐рд░реНрдпрд╛рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдореБрдЭреЗ рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рдорд┐рд▓рд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗред
import React, { useContext, useEffect } from 'react';
import DndProvider, { DndContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import Frame, { FrameContext } from 'react-frame-component';
const DndFrame = ({ children }) => {
const { dragDropManager } = useContext(DndContext);
const { window } = useContext(FrameContext);
useEffect(() => {
dragDropManager.getBackend().addEventListeners(window);
});
return children;
};
const Example = () => (
<DndProvider backend={HTML5Backend}>
<Frame>
<DndFrame>
<div>...</div>
</DndFrame>
</Frame>
</DndProvider>
);
@HsuTing рдпрд╣ рдЖрд╕рд╛рди рдФрд░ рдмреЗрд╣рддрд░ рд╣реИред рд▓реЗрдХрд┐рди рдЕрднреА рднреА HTML5Backend рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рд╣реИред рдпрджрд┐ HTML5Backend addEventListeners => addListeners рдХреЛ рдмрджрд▓рддрд╛ рд╣реИ, рддреЛ рд╣рдорд╛рд░рд╛ рд╡реЗрдм рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░, рдЬрдм рдореИрдВ рд╣рд╛рдЗрдХ рд╕реЗ рд╡рд╛рдкрд╕ рдЖрдКрдВрдЧрд╛ рддреЛ рдореИрдВ рдЗрд╕рдХреЗ рд╕рд╛рде рдЦреЗрд▓реВрдВрдЧрд╛
рдордВрдЧрд▓рд╡рд╛рд░, рдЕрдЧрд╕реНрдд 6, 2019, рд░рд╛рдд 11:43 рдмрдЬреЗ [email protected] рдиреЗ рд▓рд┐рдЦрд╛:
@HsuTing https://github.com/HsuTing рдпрд╣ рдЖрд╕рд╛рди рдФрд░ рдмреЗрд╣рддрд░ рд╣реИред рдлрд┐рд░ рднреА
HTML5Backend рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдпред рдпрджрд┐ HTML5рдмреИрдХрдПрдВрдб рдПрдбрдПрд╡реЗрдВрдЯ рд▓рд┐рд╕реНрдЯрдирд░ рдмрджрд▓рддрд╛ рд╣реИ
=> рд╢реНрд░реЛрддрд╛рдУрдВ рдХреЛ рдЬреЛрдбрд╝реЗрдВ, рд╣рдорд╛рд░рд╛ рд╡реЗрдм рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛-
рдЖрдк рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рдЕрд╕рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ, рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
рдХреЙрдо
рдпрд╛ рдереНрд░реЗрдб рдХреЛ рдореНрдпреВрдЯ рдХрд░реЗрдВ
https://github.com/notifications/unsubscribe-auth/AAA3XCGHNHO3M3CSL5VRUQTQDJVJLANCNFSM4IIMWOQQ
.
рдореБрдЭреЗ рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рдорд┐рд▓рд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗред
import React, { useContext, useEffect } from 'react'; import DndProvider, { DndContext } from 'react-dnd'; import HTML5Backend from 'react-dnd-html5-backend'; import Frame, { FrameContext } from 'react-frame-component'; const DndFrame = ({ children }) => { const { dragDropManager } = useContext(DndContext); const { window } = useContext(FrameContext); useEffect(() => { dragDropManager.getBackend().addEventListeners(window); }); return children; }; const Example = () => ( <DndProvider backend={HTML5Backend}> <Frame> <DndFrame> <div>...</div> </DndFrame> </Frame> </DndProvider> );
рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ рдФрд░ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдореБрдЭреЗ рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рдорд┐рд▓рд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗред
import React, { useContext, useEffect } from 'react'; import DndProvider, { DndContext } from 'react-dnd'; import HTML5Backend from 'react-dnd-html5-backend'; import Frame, { FrameContext } from 'react-frame-component'; const DndFrame = ({ children }) => { const { dragDropManager } = useContext(DndContext); const { window } = useContext(FrameContext); useEffect(() => { dragDropManager.getBackend().addEventListeners(window); }); return children; }; const Example = () => ( <DndProvider backend={HTML5Backend}> <Frame> <DndFrame> <div>...</div> </DndFrame> </Frame> </DndProvider> );
рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рдХреЗ рд╕рд╛рде рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рдореБрдЭреЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ Property 'addEventListeners' does not exist on type 'Backend'
рдХреНрдпрд╛ рдЯреАрдПрд╕ рдореЗрдВ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ?
addEventListeners рдмреИрдХрдПрдВрдб рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкрд░ рдЙрдЬрд╛рдЧрд░ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ; рдФрд░ рдореИрдВ рдЗрд╕рдХрд╛ рдЦреБрд▓рд╛рд╕рд╛ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдбреЛрдо/рдмреНрд░рд╛рдЙрдЬрд╝рд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдЬреЛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рд╡рд╣ рдХреБрдЫ рдРрд╕рд╛ рд╣реИ:
// detect if SSR mode
const DEFAULT_GLOBAL_CONTEXT = typeof window !== 'undefined' ? window : global
const DndFrame = ({ children, globalContext = DEFAULT_GLOBAL_CONTEXT}) => {
const { dragDropManager } = useContext(DndContext);
const { window } = useContext(FrameContext);
const backend = useMemo(() => dragDropManager.getBackend(), [dragDropManager])
useEffect(() => {
// This will required adding an initialize() method to the Backend interface.
// Backend constructors will have to thunk over to it. It could replace constructors, but that would be semver major.
backend.initialize(dragDropManager, globalContext)
backend.setup()
}, [globalContext]);
return children;
};
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдореБрдЭреЗ рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рдорд┐рд▓рд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдмреЗрд╣рддрд░ рд╕рдорд╛рдзрд╛рди рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗред