vtils
Version:
一个面向业务的 JavaScript/TypeScript 实用程序库。
107 lines (106 loc) • 3.55 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import React from 'react';
import ReactDOM from 'react-dom';
import { isPromiseLike } from "../utils/index.js";
import { useUpdate } from 'react-use';
/**
* 独立渲染一个组件在 document.body 下,常应用于弹窗类组件。
*
* @param Component 要渲染的组件
* @param initialProps 初始属性
* @param injectCallbacks 回调函数注入
*/
export function renderComponent(Component, initialProps, injectCallbacks) {
var hasContainer = true;
var render;
var destroy;
var prepareProps = function prepareProps(props) {
props = _extends({}, props);
if (injectCallbacks) {
var _loop = function _loop() {
var key = _Object$keys[_i];
var originalCallback = props[key];
props[key] = function () {
var res = originalCallback == null ? void 0 : originalCallback();
if (isPromiseLike(res)) {
return res.then(function () {
return injectCallbacks[key]();
});
}
return injectCallbacks[key]();
};
};
for (var _i = 0, _Object$keys = Object.keys(injectCallbacks); _i < _Object$keys.length; _i++) {
_loop();
}
}
return props;
};
if (hasRenderComponentContainer) {
var childIndex;
render = function render(props) {
props = prepareProps(props);
if (childIndex == null) {
childIndex = renderComponentContainerChildren.length;
renderComponentContainerChildren.push(React.createElement(Component, props));
} else {
renderComponentContainerChildren.splice(childIndex, 1, React.createElement(Component, props));
}
updateRenderComponentContainer();
};
destroy = function destroy() {
if (childIndex != null) {
renderComponentContainerChildren.splice(childIndex, 1);
updateRenderComponentContainer();
}
};
} else {
var container = document.createElement('div');
document.body.appendChild(container);
render = function render(props) {
props = prepareProps(props);
ReactDOM.render(React.createElement(Component, props), container);
};
destroy = function destroy() {
if (!hasContainer || !container) return;
var unmountResult = ReactDOM.unmountComponentAtNode(container);
if (unmountResult) {
var _container$parentNode;
(_container$parentNode = container.parentNode) == null || _container$parentNode.removeChild(container);
}
container = null;
hasContainer = false;
};
}
var incrementalProps = _extends({
key: Date.now()
}, initialProps);
render(incrementalProps);
return {
incrementalRerender: function incrementalRerender(props) {
if (!hasContainer) return;
incrementalProps = _extends({}, incrementalProps, props);
render(incrementalProps);
},
partialRerender: function partialRerender(props) {
if (!hasContainer) return;
render(_extends({}, initialProps, props));
},
fullRerender: function fullRerender(props) {
if (!hasContainer) return;
render(props);
},
destroy: destroy
};
}
// 渲染容器
var hasRenderComponentContainer = false;
var updateRenderComponentContainer;
var renderComponentContainerChildren = [];
export function RenderComponentContainer() {
hasRenderComponentContainer = true;
updateRenderComponentContainer = useUpdate();
return React.createElement(React.Fragment, {
children: renderComponentContainerChildren
});
}