zent
Version:
一套前端设计语言和基于React的实现
97 lines (75 loc) • 2.97 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getNodeFromSelector = getNodeFromSelector;
exports.prepareNode = prepareNode;
exports.openPortal = openPortal;
exports.destroyPortal = destroyPortal;
var _classnames = require('zent-utils/classnames');
var _classnames2 = _interopRequireDefault(_classnames);
var _react = require('react');
var _reactDom = require('react-dom');
var _reactDom2 = _interopRequireDefault(_reactDom);
var _isFunction = require('zent-utils/lodash/isFunction');
var _isFunction2 = _interopRequireDefault(_isFunction);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function createContainerNode(parent) {
var div = document.createElement('div');
return parent.appendChild(div);
}
function removeNodeFromDOMTree(node) {
var parentNode = node.parentNode;
if (parentNode) {
parentNode.removeChild(node);
}
}
function getNodeFromSelector(selector) {
var node = typeof selector === 'string' ? document.querySelector(selector) : selector;
return node || document.body;
}
function prepareNode(node, prefix, className, css) {
node.className = (0, _classnames2['default'])(prefix + '-portal', className);
node.style.cssText = Object.keys(css || {}).map(function (k) {
return k + ': ' + css[k];
}).join('; ');
}
function openPortal(props) {
props = props || this.props;
// 确保container存在,这个container是必须的,因为React的render会覆盖这个节点下的所有东西。
var node = this.node;
if (!node) {
var _props = props,
selector = _props.selector,
prefix = _props.prefix,
className = _props.className,
css = _props.css;
var parentNode = getNodeFromSelector(selector);
this.node = node = createContainerNode(parentNode);
prepareNode(node, prefix, className, css);
}
// 这个API虽然是unstable,但是现在实现portal只能用它,如果用ReactDOM.render会导致
// context失效。
var _props2 = props,
children = _props2.children;
_reactDom2['default'].unstable_renderSubtreeIntoContainer(this, _react.Children.only(children), node);
}
function destroyPortal(callback) {
var _this = this;
var node = this.node;
if (node) {
// React不支持在event handler中unmount组件,会引起问题。Portal的使用场景很容易出现
// 这种情况,比如在portal内部按了关闭按钮关掉portal。setTimeout的作用是把unmount放到下一个tick
// 中去做。
//
// Invariant Violation: React DOM tree root should always have a node reference.
// https://github.com/facebook/react/issues/2605
// https://github.com/facebook/react/issues/3298
setTimeout(function () {
_reactDom2['default'].unmountComponentAtNode(node);
removeNodeFromDOMTree(node);
_this.node = undefined;
(0, _isFunction2['default'])(callback) && callback();
}, 0);
}
}
;