UNPKG

react-activation

Version:

<KeepAlive /> for React like <keep-alive /> in vue

1,467 lines (1,428 loc) 77.4 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var _flatten = _interopDefault(require('szfe-tools/lib/flatten')); var _get = _interopDefault(require('szfe-tools/lib/get')); var _run = _interopDefault(require('szfe-tools/lib/run')); var _debounce = _interopDefault(require('szfe-tools/lib/debounce')); var React = require('react'); var React__default = _interopDefault(React); var _isFunction = _interopDefault(require('szfe-tools/lib/isFunction')); var _random = _interopDefault(require('szfe-tools/lib/random')); var _EventBus = _interopDefault(require('szfe-tools/lib/EventBus')); var _nextTick = _interopDefault(require('szfe-tools/lib/nextTick')); var reactDom = require('react-dom'); var _isString = _interopDefault(require('szfe-tools/lib/isString')); var _isExist = _interopDefault(require('szfe-tools/lib/isExist')); var _memoize = _interopDefault(require('szfe-tools/lib/memoize')); var _isUndefined = _interopDefault(require('szfe-tools/lib/isUndefined')); var _isObject = _interopDefault(require('szfe-tools/lib/isObject')); var hoistStatics = _interopDefault(require('hoist-non-react-statics')); var _value = _interopDefault(require('szfe-tools/lib/value')); var _isArray = _interopDefault(require('szfe-tools/lib/isArray')); var _globalThis = _interopDefault(require('szfe-tools/lib/globalThis')); var NodeKey = _interopDefault(require('react-node-key')); function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _toArray(r) { return _arrayWithHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableRest(); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } // 值类型判断 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ var isRegExp = function isRegExp(val) { return val instanceof RegExp; }; // 值类型判断 ------------------------------------------------------------- var MAX_SIGNED_31_BIT_INT = 1073741823; // Inlined Object.is polyfill. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is function objectIs(x, y) {} function createEventEmitter(value) { var handlers = []; return { on: function on(handler) { handlers.push(handler); }, off: function off(handler) { handlers = handlers.filter(function (h) { return h !== handler; }); }, get: function get() { return value; }, set: function set(newValue, changedBits) { value = newValue; handlers.forEach(function (handler) { return handler(value, changedBits); }); } }; } function onlyChild(children) { return Array.isArray(children) ? children[0] : children; } function createReactContext(defaultValue, calculateChangedBits) { var contextProp = '__create-react-context-' + _random() + '__'; var Provider = /*#__PURE__*/function (_Component) { function Provider() { var _this; _classCallCheck(this, Provider); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, Provider, [].concat(args)); _defineProperty(_this, "emitter", createEventEmitter(_this.props.value)); return _this; } _inherits(Provider, _Component); return _createClass(Provider, [{ key: "getChildContext", value: function getChildContext() { return _defineProperty({}, contextProp, this.emitter); } }, { key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { if (this.props.value !== nextProps.value) { var oldValue = this.props.value; var newValue = nextProps.value; var changedBits; if (objectIs()) { changedBits = 0; // No change } else { changedBits = typeof calculateChangedBits === 'function' ? calculateChangedBits(oldValue, newValue) : MAX_SIGNED_31_BIT_INT; changedBits |= 0; if (changedBits !== 0) { this.emitter.set(nextProps.value, changedBits); } } } } }, { key: "render", value: function render() { return this.props.children; } }]); }(React.Component); var Consumer = /*#__PURE__*/function (_Component2) { function Consumer() { var _this2; _classCallCheck(this, Consumer); for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } _this2 = _callSuper(this, Consumer, [].concat(args)); _defineProperty(_this2, "observedBits", void 0); _defineProperty(_this2, "state", { value: _this2.getValue() }); _defineProperty(_this2, "onUpdate", function (newValue, changedBits) { var observedBits = _this2.observedBits | 0; if ((observedBits & changedBits) !== 0) { _this2.setState({ value: _this2.getValue() }); } }); return _this2; } _inherits(Consumer, _Component2); return _createClass(Consumer, [{ key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { var observedBits = nextProps.observedBits; this.observedBits = observedBits === undefined || observedBits === null ? MAX_SIGNED_31_BIT_INT // Subscribe to all changes by default : observedBits; } }, { key: "componentDidMount", value: function componentDidMount() { if (this.context[contextProp]) { this.context[contextProp].on(this.onUpdate); } var observedBits = this.props.observedBits; this.observedBits = observedBits === undefined || observedBits === null ? MAX_SIGNED_31_BIT_INT // Subscribe to all changes by default : observedBits; } }, { key: "componentWillUnmount", value: function componentWillUnmount() { if (this.context[contextProp]) { this.context[contextProp].off(this.onUpdate); } } }, { key: "getValue", value: function getValue() { if (this.context[contextProp]) { return this.context[contextProp].get(); } else { return defaultValue; } } }, { key: "render", value: function render() { return onlyChild(this.props.children)(this.state.value); } }]); }(React.Component); return { Provider: Provider, Consumer: Consumer }; } var createReactContext$1 = React__default.createContext || createReactContext; var aliveScopeContext = createReactContext$1(); var AliveScopeProvider = aliveScopeContext.Provider, AliveScopeConsumer = aliveScopeContext.Consumer; var aliveNodeContext = createReactContext$1(); var AliveNodeProvider = aliveNodeContext.Provider, AliveNodeConsumer = aliveNodeContext.Consumer; var eventBus = new _EventBus(); var FakeScopeProvider = /*#__PURE__*/function (_Component) { function FakeScopeProvider(props) { var _this; _classCallCheck(this, FakeScopeProvider); _this = _callSuper(this, FakeScopeProvider, [props]); FakeScopeProvider.currentContextValue = props.value; return _this; } _inherits(FakeScopeProvider, _Component); return _createClass(FakeScopeProvider, [{ key: "shouldComponentUpdate", value: function shouldComponentUpdate(nextProps) { if (nextProps.value !== this.props.value) { FakeScopeProvider.currentContextValue = nextProps.value; eventBus.emit('update', nextProps.value); } return nextProps.children !== this.props.children || nextProps.value !== this.props.value; } }, { key: "render", value: function render() { var children = this.props.children; return children; } }]); }(React.Component); _defineProperty(FakeScopeProvider, "eventBus", eventBus); _defineProperty(FakeScopeProvider, "currentContextValue", undefined); var FakeScopeConsumer = /*#__PURE__*/function (_PureComponent) { function FakeScopeConsumer(props) { var _this2; _classCallCheck(this, FakeScopeConsumer); _this2 = _callSuper(this, FakeScopeConsumer, [props]); _defineProperty(_this2, "state", { context: FakeScopeProvider.currentContextValue }); _defineProperty(_this2, "updateListener", _debounce(function (nextContextValue) { _this2.setState({ context: nextContextValue }); })); eventBus.on('update', _this2.updateListener); return _this2; } _inherits(FakeScopeConsumer, _PureComponent); return _createClass(FakeScopeConsumer, [{ key: "componentWillUnmount", value: function componentWillUnmount() { eventBus.off('update', this.updateListener); } }, { key: "render", value: function render() { var children = this.props.children; var context = this.state.context; return _run(children, undefined, context); } }]); }(React.PureComponent); var _excluded = ["children"]; var _filehash = "qj9A"; var useScopeContext = function useScopeContext() { if (!_isFunction(React.useContext)) { return {}; } var scopeReactContext = React.useContext(aliveScopeContext); if (scopeReactContext) { return scopeReactContext; } var _useState = React.useState(FakeScopeProvider.currentContextValue), _useState2 = _slicedToArray(_useState, 2), context = _useState2[0], setContext = _useState2[1]; React.useEffect(function () { var updateListener = _debounce(setContext); eventBus.on('update', updateListener); return function () { return eventBus.off('update', updateListener); }; }, []); return context; }; var AliveScopeProvider$1 = function AliveScopeProvider$1(_ref) { var children = _ref.children, props = _objectWithoutProperties(_ref, _excluded); return /*#__PURE__*/React__default.createElement(AliveScopeProvider, _extends({}, props, { _nk: "".concat(_filehash, "11") }), /*#__PURE__*/React__default.createElement(FakeScopeProvider, _extends({}, props, { _nk: "".concat(_filehash, "21") }), children)); }; var AliveScopeConsumer$1 = function AliveScopeConsumer$1(_ref2) { var children = _ref2.children; return /*#__PURE__*/React__default.createElement(AliveScopeConsumer, { _nk: "".concat(_filehash, "31") }, function (reactContext) { return !!reactContext ? _run(children, undefined, reactContext) : /*#__PURE__*/React__default.createElement(FakeScopeConsumer, { _nk: "".concat(_filehash, "41") }, children); }); }; // function Suspender({ freeze, children }) { // const promiseCache = useRef({}).current // if (freeze && !promiseCache.promise) { // promiseCache.promise = new Promise((resolve) => { // promiseCache.resolve = resolve // }) // throw promiseCache.promise // } else if (freeze) { // throw promiseCache.promise // } else if (promiseCache.promise) { // promiseCache.resolve() // promiseCache.promise = undefined // } // return <Fragment>{children}</Fragment> // } var _filehash$1 = "Leb+"; var Suspender = /*#__PURE__*/function (_Component) { function Suspender() { var _this; _classCallCheck(this, Suspender); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, Suspender, [].concat(args)); _defineProperty(_this, "promiseCache", {}); return _this; } _inherits(Suspender, _Component); return _createClass(Suspender, [{ key: "render", value: function render() { var _this$props = this.props, freeze = _this$props.freeze, children = _this$props.children; var promiseCache = this.promiseCache; if (freeze && !promiseCache.promise) { promiseCache.promise = new Promise(function (resolve) { promiseCache.resolve = resolve; }); throw promiseCache.promise; } else if (freeze) { throw promiseCache.promise; } else if (promiseCache.promise) { promiseCache.resolve(); promiseCache.promise = undefined; } return /*#__PURE__*/React__default.createElement(React.Fragment, null, children); } }]); }(React.Component); function Freeze(_ref) { var freeze = _ref.freeze, children = _ref.children, _ref$placeholder = _ref.placeholder, placeholder = _ref$placeholder === void 0 ? null : _ref$placeholder; return /*#__PURE__*/React__default.createElement(React.Suspense, { fallback: placeholder, _nk: "".concat(_filehash$1, "11") }, /*#__PURE__*/React__default.createElement(Suspender, { freeze: freeze, _nk: "".concat(_filehash$1, "21") }, children)); } var fixedContext = []; var updateListenerCache = new Map(); var eventBus$1 = new _EventBus(); var fixContext = _memoize(function (ctx) { if (!_isExist(ctx)) { return; } // 排除 KeepAlive 功能的上下文 if ([aliveScopeContext, aliveNodeContext].includes(ctx)) { return; } // #259: 结合 use-context-selector 时,修复被删除的 Consumer if (!_isExist(ctx.Consumer)) { var Consumer = function Consumer(_ref) { var children = _ref.children; var ctxValue = _run(React.useContext, undefined, ctx); return /*#__PURE__*/React__default.createElement(React.Fragment, null, _run(children, undefined, ctxValue)); }; // 重新声明 Consumer ctx.Consumer = Consumer; } fixedContext.push(ctx); setTimeout(function () { return eventBus$1.emit('update'); }); }); var createContext = function createContext(defaultValue, calculateChangedBits) { var ctx = createReactContext$1(defaultValue, calculateChangedBits); fixContext(ctx); return ctx; }; var tryFixCtx = _memoize(function (type) { // 尝试读取 Provider 或 Consumer 中的 context 静态属性 var ctx = _get(type, '_context') || _get(type, 'context'); // 16.3.0 版本为 context,之后为 _context // 判断是否为 ReactContext 类型 if (_get(ctx, '$$typeof') === _get(aliveScopeContext, '$$typeof')) { fixContext(ctx); } }); var override = function override(configs) { configs.forEach(function (_ref2) { var _ref3 = _toArray(_ref2), host = _ref3[0], methods = _ref3.slice(1); methods.forEach(function (method) { if (!_isFunction(_get(host, method)) || _get(host, [method, '_overridden'])) { return; } var originMethod = host[method].bind(host); host[method] = function (type) { if (!_isString(type)) { tryFixCtx(type); } for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return originMethod.apply(void 0, [type].concat(args)); }; host[method]._overridden = true; }); }); }; /** * 通过覆写 React.createElement 方法来探测 Provider 或 Consumer 的创建,并攫取其中 context 主动进行修复 * TODO:同时兼容 React 17+,目前仅默认兼容 React.createElement 方法 * React 17+ 为 require('react/jsx-runtime') 或 require('react/jsx-dev-runtime') 的 jsx、jsxs、jsxDEV 方法 * 但由于无法动态 require,暂未想到方式同时兼容 * 若需兼容 17+,目前手法为 * * autoFixContext( * [require('react/jsx-runtime'), 'jsx', 'jsxs', 'jsxDEV'], * [require('react/jsx-dev-runtime'), 'jsx', 'jsxs', 'jsxDEV'] * ) * * Note: 需注意 16.2.x 及以下版本不支持此方法 */ var autoFixContext = function autoFixContext() { try { for (var _len2 = arguments.length, configs = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { configs[_key2] = arguments[_key2]; } override(configs); } catch (err) { console.warn('activation override failed:', err); } }; autoFixContext([React__default, 'createElement']); var _filehash$2 = "lqEk"; var ProviderBridge = /*#__PURE__*/function (_PureComponent) { function ProviderBridge(props) { var _this; _classCallCheck(this, ProviderBridge); _this = _callSuper(this, ProviderBridge, [props]); _defineProperty(_this, "unmount", null); var ctxValues = props.value; if (ctxValues.length === 0) { _this.state = { ctxValue: null }; return _possibleConstructorReturn(_this); } var _ctxValues = _slicedToArray(ctxValues, 1), _ctxValues$ = _ctxValues[0], ctx = _ctxValues$.ctx, value = _ctxValues$.value, onUpdate = _ctxValues$.onUpdate; _this.state = { ctxValue: value }; _this.unmount = onUpdate(function (value) { _this.setState({ ctxValue: value }); }); return _this; } _inherits(ProviderBridge, _PureComponent); return _createClass(ProviderBridge, [{ key: "componentWillUnmount", value: function componentWillUnmount() { _run(this.unmount); } // componentDidCatch(error) { // console.error('ProviderBridge Error', error) // } }, { key: "render", value: function render() { var _this$props = this.props, propCtxValues = _this$props.value, children = _this$props.children; var ctxValues = propCtxValues.filter(Boolean); if (ctxValues.length === 0) { return children; } var ctxValue = this.state.ctxValue; var _ctxValues2 = _toArray(ctxValues), ctx = _ctxValues2[0].ctx, restValues = _ctxValues2.slice(1); var Provider = ctx.Provider; var nextChildren = !_isUndefined(ctxValue) ? /*#__PURE__*/React__default.createElement(Provider, { value: ctxValue, _nk: "".concat(_filehash$2, "11") }, children) : children; // 递归 ProviderBridge 修复多个上下文 // 此处未考虑待修复上下文顺序问题,按先来后到顺序处理,但理论上不应存在顺序问题 return restValues.length > 0 ? /*#__PURE__*/React__default.createElement(ProviderBridge, { value: restValues, _nk: "".concat(_filehash$2, "21") }, nextChildren) : nextChildren; } }]); }(React.PureComponent); var ConsumerWrapper = /*#__PURE__*/function (_Component) { function ConsumerWrapper(props) { var _this; _classCallCheck(this, ConsumerWrapper); _this = _callSuper(this, ConsumerWrapper, [props]); _defineProperty(_this, "updateListener", null); _defineProperty(_this, "ctxInfo", null); var value = props.value, ctx = props.ctx, id = props.id; if (_isUndefined(value)) { return _possibleConstructorReturn(_this); } // 因 Consumer 探测器存在于 KeepAlive 外层故会随着 KeepAlive 卸载 // componentWillUnmount 中保留了已生成的更新监听器 // 此处重新挂载后恢复与对应 Keeper 中 ProviderBridge 的联系 _this.updateListener = _get(updateListenerCache.get(ctx), id, new Map()); _run(_this.updateListener, 'forEach', function (fn) { return fn(value); }); _this.ctxInfo = { ctx: ctx, value: value, // 注册上下文更新的监听,保证上下文更新时 Keeper 中 ProviderBridge 内容的同步 onUpdate: function onUpdate(updator) { _this.updateListener.set(updator, updator); // 返回更新监听器的注销方法 return function () { return _this.updateListener["delete"](updator); }; } }; return _this; } _inherits(ConsumerWrapper, _Component); return _createClass(ConsumerWrapper, [{ key: "componentWillUnmount", value: function componentWillUnmount() { var _this$props = this.props, value = _this$props.value, ctx = _this$props.ctx, id = _this$props.id; if (_isUndefined(value)) { return; } // 因 Consumer 探测器存在于 KeepAlive 外层故会随着 KeepAlive 卸载 // 此处保留其中已生成的更新监听器,用以在重新挂载后保持与对应 Keeper 中 ProviderBridge 的联系 updateListenerCache.set(ctx, _objectSpread2(_objectSpread2({}, _get(updateListenerCache.get(ctx), undefined, {})), {}, _defineProperty({}, id, this.updateListener))); } // 利用 shouldComponentUpdate 尽早将上下文更新的咨询通知到对应 Keeper 中 ProviderBridge // TODO: 改用 componentWillReceiveProps 更早地进行更新,需注意与 getDerivedStateFromProps 新生命周期的兼容及可能存在的死循环问题 }, { key: "shouldComponentUpdate", value: function shouldComponentUpdate(_ref) { var value = _ref.value; var prevValue = this.props.value; var shouldUpdate = prevValue !== value; if (shouldUpdate) { _run(this.updateListener, 'forEach', function (fn) { return fn(value); }); } return true; } }, { key: "render", value: function render() { var _this2 = this; var _this$props2 = this.props, value = _this$props2.value, renderWrapper = _this$props2.renderWrapper, renderContent = _this$props2.renderContent, id = _this$props2.id; return renderWrapper(function (ctx$$) { return renderContent(_isUndefined(value) ? ctx$$ : [].concat(_toConsumableArray(ctx$$), [_this2.ctxInfo])); }); } }]); }(React.Component); var _filehash$3 = "SsUr"; var fixedContextSnapshot = {}; // 对 ConsumerWrapper 的递归结构,会在 devtool 中生成较深的嵌套结构,可用 hooks 消除嵌套结构 var RecursiveConsumerBridge = /*#__PURE__*/function (_PureComponent) { function RecursiveConsumerBridge(props) { var _this; _classCallCheck(this, RecursiveConsumerBridge); _this = _callSuper(this, RecursiveConsumerBridge, [props]); _defineProperty(_this, "renderWrapper", function (renderChildren) { var id = _this.props.id; var renderWrapper = fixedContextSnapshot[id].reduce(function (render, ctx) { var Consumer = ctx.Consumer; var renderWrapper = function renderWrapper(renderContent) { return /*#__PURE__*/React__default.createElement(Consumer, { _nk: "".concat(_filehash$3, "11") }, function (value) { return /*#__PURE__*/React__default.createElement(ConsumerWrapper, { value: value, ctx: ctx, renderWrapper: render, renderContent: renderContent, id: id, _nk: "".concat(_filehash$3, "21") }); }); }; return renderWrapper; }, function (renderContent) { return renderContent([]); }); return renderWrapper(renderChildren); }); var _id = props.id; if (!fixedContextSnapshot[_id]) { fixedContextSnapshot[_id] = _toConsumableArray(fixedContext).filter(function (ctx) { return _isExist(ctx.Consumer); }); } return _this; } _inherits(RecursiveConsumerBridge, _PureComponent); return _createClass(RecursiveConsumerBridge, [{ key: "render", value: function render() { var renderChildren = this.props.children; return this.renderWrapper(renderChildren); } }]); }(React.PureComponent); // 若支持 Hooks,就不需要递归了,相关实现解释可参考 ConsumerWrapper // 兼容性检测 var _filehash$4 = "46lG"; var isSupported = _isFunction(React.lazy) && !_isUndefined(React.Suspense); var SusNotSupported = function SusNotSupported(_ref) { var children = _ref.children; return _run(children); }; var Lazy = isSupported ? /*#__PURE__*/React.lazy(function () { return new Promise(function () { return null; }); }) : function () { return null; }; var FallbackListener = /*#__PURE__*/function (_Component) { function FallbackListener() { _classCallCheck(this, FallbackListener); return _callSuper(this, FallbackListener, arguments); } _inherits(FallbackListener, _Component); return _createClass(FallbackListener, [{ key: "componentDidMount", value: function componentDidMount() { _run(this.props, 'onStart'); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { _run(this.props, 'onEnd'); } }, { key: "render", value: function render() { return null; } }]); }(React.Component); function SuspenseBridge(_ref2) { var children = _ref2.children, sus$$ = _ref2.sus$$; return ( /*#__PURE__*/ // 捕获 Keeper 内部可能存在的 lazy,并触发对应 KeepAlive 位置上的 LazyBridge React__default.createElement(React.Suspense, { fallback: /*#__PURE__*/React__default.createElement(FallbackListener, { onStart: sus$$.onSuspenseStart, onEnd: sus$$.onSuspenseEnd, _nk: "".concat(_filehash$4, "21") }), _nk: "".concat(_filehash$4, "11") }, children) ); } var LazyBridge = isSupported ? /*#__PURE__*/function (_Component2) { function LazyBridge() { var _this; _classCallCheck(this, LazyBridge); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, LazyBridge, [].concat(args)); _defineProperty(_this, "state", { suspense: false }); _defineProperty(_this, "onSuspenseStart", function () { _this.setState({ suspense: true }); }); _defineProperty(_this, "onSuspenseEnd", function () { _this.setState({ suspense: false }); }); _defineProperty(_this, "sus$$", { onSuspenseStart: _this.onSuspenseStart, onSuspenseEnd: _this.onSuspenseEnd }); return _this; } _inherits(LazyBridge, _Component2); return _createClass(LazyBridge, [{ key: "render", value: function render() { var children = this.props.children; return /*#__PURE__*/React__default.createElement(React.Fragment, null, _run(children, undefined, this.sus$$), this.state.suspense && /*#__PURE__*/React__default.createElement(Lazy, { _nk: "".concat(_filehash$4, "31") })); } }]); }(React.Component) : SusNotSupported; var SuspenseBridge$1 = isSupported ? SuspenseBridge : SusNotSupported; var ErrorBoundaryBridge = /*#__PURE__*/function (_Component) { function ErrorBoundaryBridge() { _classCallCheck(this, ErrorBoundaryBridge); return _callSuper(this, ErrorBoundaryBridge, arguments); } _inherits(ErrorBoundaryBridge, _Component); return _createClass(ErrorBoundaryBridge, [{ key: "componentDidCatch", value: function componentDidCatch(error) { var throwError = this.props.error$$; _run(throwError, undefined, error, function () { _run(throwError, undefined, null); }); } }, { key: "render", value: function render() { return this.props.children; } }]); }(React.Component); // Error Boundary 透传至对应 KeepAlive 实例位置 _defineProperty(ErrorBoundaryBridge, "getDerivedStateFromError", function () { return null; }); var ErrorThrower = /*#__PURE__*/function (_Component2) { function ErrorThrower() { var _this; _classCallCheck(this, ErrorThrower); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, ErrorThrower, [].concat(args)); _defineProperty(_this, "state", { error: null }); _defineProperty(_this, "throwError", function (error, cb) { return _this.setState({ error: error }, cb); }); return _this; } _inherits(ErrorThrower, _Component2); return _createClass(ErrorThrower, [{ key: "render", value: function render() { if (this.state.error) { throw this.state.error; } return _run(this.props.children, undefined, this.throwError); } }]); }(React.Component); // 用于 Keeper 中,实现 Keeper 向外或向内的桥接代理 var _filehash$5 = "lajT"; function Bridge(_ref) { var id = _ref.id, children = _ref.children, bridgeProps = _ref.bridgeProps; var sus$$ = bridgeProps.sus$$, ctx$$ = bridgeProps.ctx$$, error$$ = bridgeProps.error$$; return /*#__PURE__*/ /* 由内向外透传 componentDidCatch 捕获的 error */React__default.createElement(ErrorBoundaryBridge, { error$$: error$$, _nk: "".concat(_filehash$5, "11") }, /*#__PURE__*/React__default.createElement(SuspenseBridge$1, { sus$$: sus$$, _nk: "".concat(_filehash$5, "21") }, /*#__PURE__*/React__default.createElement(ProviderBridge, { id: id, value: ctx$$, _nk: "".concat(_filehash$5, "31") }, children))); } // 用于 KeepAlive 中,实现 KeepAlive 向外或向内的桥接代理 function Acceptor(_ref2) { var id = _ref2.id, children = _ref2.children; return /*#__PURE__*/ /* 由内向外透传 componentDidCatch 捕获的 error */React__default.createElement(ErrorThrower, { _nk: "".concat(_filehash$5, "41") }, function (error$$) { return /*#__PURE__*/ /* 由内向外透传 lazy 行为 */React__default.createElement(LazyBridge, { _nk: "".concat(_filehash$5, "51") }, function (sus$$) { return /*#__PURE__*/ /* 由外向内透传可能被捕获的 Provider 数据 */React__default.createElement(RecursiveConsumerBridge, { id: id, _nk: "".concat(_filehash$5, "61") }, function (ctx$$) { return _run(children, undefined, { bridgeProps: { sus$$: sus$$, ctx$$: ctx$$, error$$: error$$ } }); }); }); }); } var _excluded$1 = ["forwardedRef"]; var _filehash$6 = "XKTv"; var LIFECYCLE_ACTIVATE = 'componentDidActivate'; var LIFECYCLE_UNACTIVATE = 'componentWillUnactivate'; var withActivation = function withActivation(WrappedComponent) { var HOC = /*#__PURE__*/function (_Component) { function HOC() { var _this; _classCallCheck(this, HOC); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, HOC, [].concat(args)); _defineProperty(_this, "drop", null); return _this; } _inherits(HOC, _Component); return _createClass(HOC, [{ key: "componentWillUnmount", value: function componentWillUnmount() { _run(this.drop); } }, { key: "render", value: function render() { var _this2 = this; var _this$props = this.props, forwardedRef = _this$props.forwardedRef, props = _objectWithoutProperties(_this$props, _excluded$1); return /*#__PURE__*/React__default.createElement(AliveNodeConsumer, { _nk: "".concat(_filehash$6, "11") }, function () { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, attach = _ref.attach; return /*#__PURE__*/React__default.createElement(WrappedComponent, _extends({ ref: function ref(_ref2) { if ([LIFECYCLE_ACTIVATE, LIFECYCLE_UNACTIVATE].every(function (lifecycleName) { return !_isFunction(_get(_ref2, lifecycleName)); })) { return; } _this2.drop = _run(attach, undefined, _ref2); // 以下保持 ref 功能 if (_isUndefined(forwardedRef)) { return; } if (_isObject(forwardedRef) && 'current' in forwardedRef) { forwardedRef.current = _ref2; return; } _run(forwardedRef, undefined, _ref2); } }, props, { _nk: "".concat(_filehash$6, "21") })); }); } }]); }(React.Component); // 由于 KeepAlive 内组件渲染与实际内容落后一个节拍 // 将导致真实节点的 componentDidMount 无法及时获取到 KeepAlive 中内容的 ref 值 // 此处对使用了 withActivation HOC 的组件 componentDidMount 做 nextTick 延时处理 // 修复上述问题 if (_isFunction(WrappedComponent.prototype.componentDidMount)) { WrappedComponent.prototype._componentDidMount = WrappedComponent.prototype.componentDidMount; WrappedComponent.prototype.componentDidMount = function componentDidMount() { var _this3 = this; _nextTick(function () { return WrappedComponent.prototype._componentDidMount.call(_this3); }); }; } if (_isFunction(React.forwardRef)) { var ForwardedRefHOC = /*#__PURE__*/React.forwardRef(function (props, ref) { return /*#__PURE__*/React__default.createElement(HOC, _extends({}, props, { forwardedRef: ref, _nk: "".concat(_filehash$6, "31") })); }); return hoistStatics(ForwardedRefHOC, WrappedComponent); } else { return hoistStatics(HOC, WrappedComponent); } }; var useActivation = function useActivation(funcName, func) { // 兼容性判断 if ([React.useRef, React.useContext, React.useEffect].some(function (fn) { return !_isFunction(fn); })) { return; } var ctxValue = React.useContext(aliveNodeContext); // 未处于 KeepAlive 中 if (!ctxValue) { return; } var _useRef = React.useRef({}), ref = _useRef.current; var attach = ctxValue.attach; ref[funcName] = func; ref.drop = attach(ref); React.useEffect(function () { return function () { return _run(ref.drop); }; }, []); }; var useActivate = useActivation.bind(null, LIFECYCLE_ACTIVATE); var useUnactivate = useActivation.bind(null, LIFECYCLE_UNACTIVATE); var _excluded$2 = ["id", "autoFreeze", "contentProps"]; var _filehash$7 = "bNyU"; var Freeze$1 = !!React.Suspense ? Freeze : function (_ref) { var children = _ref.children; return children; }; var Keeper = /*#__PURE__*/function (_PureComponent) { function Keeper(props) { var _this; _classCallCheck(this, Keeper); for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { rest[_key - 1] = arguments[_key]; } _this = _callSuper(this, Keeper, [props].concat(rest)); _defineProperty(_this, "eventBus", new _EventBus()); _defineProperty(_this, "listeners", new Map()); _defineProperty(_this, "wrapper", null); _defineProperty(_this, "cache", undefined); _defineProperty(_this, "unmounted", false); _defineProperty(_this, "safeSetState", function (nextState, callback) { // fix #170 if (_this.unmounted) { return; } _this.setState(nextState, callback); }); _defineProperty(_this, "freezeTimeout", null); // // 原先打算更新过程中先重置 dom 节点状态,更新后恢复 dom 节点 // // 但考虑到性能消耗可能过大,且可能因 dom 操作时机引发其他 react 渲染问题,故不使用 // // 对应 KeepAlive 处 update 也注释起来不使用 // // 组件更新后,更新 DOM 节点列表状态 // componentDidUpdate() { // const { store, id } = this.props // const node = this.wrapper // if (get(node, 'children.length') > 0) { // store[id].nodes = [...node.children] // } // console.log(store[id].nodes) // } // 生命周期绑定 _defineProperty(_this, "attach", function (ref) { var listeners = _this.listeners; if (!ref) { return function () { return null; }; } if (ref.isKeepAlive) { _nextTick(function () { var _this$props = _this.props, id = _this$props.id, store = _this$props.store; var cache = store.get(id); cache.aliveNodesId = new Set([].concat(_toConsumableArray(cache.aliveNodesId), [ref.id])); }); } listeners.set(ref, _defineProperty(_defineProperty({}, LIFECYCLE_ACTIVATE, function () { return _run(ref, LIFECYCLE_ACTIVATE); }), LIFECYCLE_UNACTIVATE, function () { return _run(ref, LIFECYCLE_UNACTIVATE); })); // 返回 listenerRemover 用以在对应组件卸载时解除监听 return function () { listeners["delete"](ref); }; }); // 静态化节点上下文内容,防止重复渲染 _defineProperty(_this, "contextValue", { id: _this.props.id, attach: _this.attach }); _defineProperty(_this, "drop", function () { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref2$delay = _ref2.delay, delay = _ref2$delay === void 0 ? 1200 : _ref2$delay, _ref2$refreshIfDropFa = _ref2.refreshIfDropFailed, refreshIfDropFailed = _ref2$refreshIfDropFa === void 0 ? true : _ref2$refreshIfDropFa; return new Promise(function (resolve) { var timeout; var _this$props2 = _this.props, scope = _this$props2.scope, id = _this$props2.id; var _drop = function drop() { clearTimeout(timeout); _this.eventBus.off(LIFECYCLE_UNACTIVATE, _drop); // 用在多层 KeepAlive 同时触发 drop 时,避免触发深层 KeepAlive 节点的缓存生命周期 _this.cache.willDrop = true; scope.nodes["delete"](id); scope.helpers = _objectSpread2({}, scope.helpers); scope.smartForceUpdate(function () { return resolve(true); }); }; var canDrop = _get(_this.cache, 'cached') || _get(_this.cache, 'willDrop'); if (!canDrop) { _this.eventBus.on(LIFECYCLE_UNACTIVATE, _drop); timeout = setTimeout(function () { _this.eventBus.off(LIFECYCLE_UNACTIVATE, _drop); if (refreshIfDropFailed) { _this.refresh().then(function (result) { return resolve(result); }); } else { resolve(false); } }, delay); return; } _drop(); }); }); _defineProperty(_this, "refresh", function () { return new Promise(function (resolve) { var canRefresh = !_get(_this.cache, 'cached'); if (!canRefresh) { resolve(false); } _this.safeSetState({ key: Math.random() }, function () { return resolve(true); }); }); }); _this.state = { children: props.children, bridgeProps: props.bridgeProps, key: Math.random(), freeze: false }; return _this; } _inherits(Keeper, _PureComponent); return _createClass(Keeper, [{ key: "componentDidMount", value: function componentDidMount() { var _this2 = this; var _this$props3 = this.props, store = _this$props3.store, id = _this$props3.id; var listeners = this.listeners; var node = this.wrapper; // 已存在检测,防止意外现象 if (store.has(id)) { return; } var nodes; try { nodes = _toConsumableArray(node.children); } catch (e) { nodes = [node.children]; } this.cache = _defineProperty(_defineProperty({ listeners: listeners, aliveNodesId: [], inited: false, cached: false, wrapper: node, nodes: nodes }, LIFECYCLE_ACTIVATE, function () { return _this2[LIFECYCLE_ACTIVATE](); }), LIFECYCLE_UNACTIVATE, function () { return _this2[LIFECYCLE_UNACTIVATE](); }); store.set(id, this.cache); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var _this$props4 = this.props, store = _this$props4.store, keepers = _this$props4.keepers, id = _this$props4.id; // 卸载前尝试归位 DOM 节点 try { var cache = store.get(id); cache.nodes.forEach(function (node) { cache.wrapper.appendChild(node); }); } catch (error) { // console.error(error) // do nothing } store["delete"](id); keepers["delete"](id); this.unmounted = true; } }, { key: LIFECYCLE_ACTIVATE, value: function value() { clearTimeout(this.freezeTimeout); // 激活后,立即解冻 this.safeSetState({ freeze: false }); this.eventBus.emit(LIFECYCLE_ACTIVATE); this.listeners.forEach(function (listener) { return _run(listener, [LIFECYCLE_ACTIVATE]); }); } }, { key: LIFECYCLE_UNACTIVATE, value: function value() { var _this3 = this; this.eventBus.emit(LIFECYCLE_UNACTIVATE); var listeners = _toConsumableArray(this.listeners); listeners.reverse().forEach(function (_ref3) { var _ref4 = _slicedToArray(_ref3, 2), listener = _ref4[1]; return _run(listener, [LIFECYCLE_UNACTIVATE]); }); // 缓存后,延迟冻结,保证各项后续处理得以进行,如关闭弹窗等 clearTimeout(this.freezeTimeout); this.freezeTimeout = setTimeout(function () { reactDom.flushSync(function () { _this3.safeSetState({ freeze: true }); }); }, 1000); } }, { key: "render", value: function render() { var _this4 = this; var _this$props5 = this.props, id = _this$props5.id, _this$props5$autoFree = _this$props5.autoFreeze, autoFreeze = _this$props5$autoFree === void 0 ? true : _this$props5$autoFree, _this$props5$contentP = _this$props5.contentProps, contentProps = _this$props5$contentP === void 0 ? {} : _this$props5$contentP, props = _objectWithoutProperties(_this$props5, _excluded$2); var _this$state = this.state, children = _this$state.children, bridgeProps = _this$state.bridgeProps, key = _this$state.key, freeze = _this$state.freeze; return /*#__PURE__*/React__default.createElement(Freeze$1, { freeze: autoFreeze && freeze, _nk: "".concat(_filehash$7, "11") }, /*#__PURE__*/React__default.createElement("div", { ref: function ref(node) { _this4.wrapper = node; }, _nk: "".concat(_filehash$7, "21") }, /*#__PURE__*/React__default.createElement("div", _extends({}, contentProps, { key: "keeper-container", className: "ka-content ".concat(contentProps.className || '') }), /*#__PURE__*/React__default.createElement(Bridge, { id: id, bridgeProps: bridgeProps, _nk: "".concat(_filehash$7, "31") }, /*#__PURE__*/React__default.createElement(AliveNodeProvider, { value: this.contextValue, _nk: "".concat(_filehash$7, "41") }, React__default.Children.map(children, function (child, idx) { return /*#__PURE__*/React__default.cloneElement(child, { key: "".concat(child.key || '', ":").concat(key, ":").concat(idx) }); })))))); } }]); }(React.PureComponent); var _excluded$3 = ["children"]; var _filehash$8 = "UVSV"; var HANDLE_TYPE_DROP = 'drop'; var HANDLE_TYPE_REFRESH = 'refresh'; var AliveScope = /*#__PURE__*/function (_Component) { function AliveScope() { var _this; _classCallCheck(this, AliveScope); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, AliveScope, [].concat(args)); _defineProperty(_this, "store", new Map()); _defineProperty(_this, "nodes", new Map()); _defineProperty(_this, "keepers", new Map()); _defineProperty(_this, "debouncedForceUpdate", _debounce(function (cb) { return _this.forceUpdate(cb); })); _defineProperty(_this, "updateCallbackList", []); _defineProperty(_this, "smartForceUpdate", function (cb) { _this.updateCallbackList.push(cb); _this.debouncedForceUpdate(function () { _this.updateCallbackList.forEach(function (cb) { return _run(cb); }); _this.updateCallbackList = []; }); }); _defineProperty(_this, "update", function (id, params) { return new Promise(function (resolve) { var keeper = _this.keepers.get(id); var isNew = !keeper; var now = Date.now(); var node = _this.nodes.get(id) || null; _this.nodes.set(id, _objectSpread2(_objectSpread2({ id: id, createTime: now, updateTime: now }, node), params)); if (isNew) { _this.helpers = _objectSpread2({}, _this.helpers); _this.forceUpdate(resolve); } else { var children = params.children, bridgeProps = params.bridgeProps; keeper.setState({ children: children, bridgeProps: bridgeProps }, resolve); } }); }); _d