UNPKG

react-activation-hyy

Version:

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

1,412 lines (1,378 loc) 63.7 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 createContext$1 = _interopDefault(require('create-react-context')); 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 s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(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 (e.includes(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; }; // 值类型判断 ------------------------------------------------------------- // 整个 KeepAlive 功能的上下文,将 KeepAlive 的组件藏于其 Provider 中,保证其不会被卸载 var aliveScopeContext = createContext$1(); var AliveScopeProvider = aliveScopeContext.Provider, AliveScopeConsumer = aliveScopeContext.Consumer; var aliveNodeContext = createContext$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 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, props, /*#__PURE__*/React__default.createElement(FakeScopeProvider, props, children)); }; var AliveScopeConsumer$1 = function AliveScopeConsumer$1(_ref2) { var children = _ref2.children; return /*#__PURE__*/React__default.createElement(AliveScopeConsumer, null, function (reactContext) { return !!reactContext ? _run(children, undefined, reactContext) : /*#__PURE__*/React__default.createElement(FakeScopeConsumer, null, 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 = createContext$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']); // 在 KeepAlive 位置使用待修复上下文的 Consumer 探测可能存在的上下文关系 // 若成功捕获上下文则保存其内容,用以后续 Keeper 中上下文的重建 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 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, null, function (value) { return /*#__PURE__*/React__default.createElement(ConsumerWrapper, { value: value, ctx: ctx, renderWrapper: render, renderContent: renderContent, id: id }); }); }; 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 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 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, null)); } }]); }(React.Component) : 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); // 用于 KeepAlive 中,实现 KeepAlive 向外或向内的桥接代理 function Acceptor(_ref2) { var id = _ref2.id, children = _ref2.children; return /*#__PURE__*/ /* 由内向外透传 componentDidCatch 捕获的 error */React__default.createElement(ErrorThrower, null, function (error$$) { return /*#__PURE__*/ /* 由内向外透传 lazy 行为 */React__default.createElement(LazyBridge, null, function (sus$$) { return /*#__PURE__*/ /* 由外向内透传可能被捕获的 Provider 数据 */React__default.createElement(RecursiveConsumerBridge, { id: id }, function (ctx$$) { return _run(children, undefined, { bridgeProps: { sus$$: sus$$, ctx$$: ctx$$, error$$: error$$ } }); }); }); }); } var _excluded$1 = ["forwardedRef"]; 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, null, 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)); }); } }]); }(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 })); }); 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"]; // const Freeze = !!Suspense ? ReactFreeze : ({ children }) => children var Freeze = function Freeze(_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, "timeStampRef", 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; 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); 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; var timeStamp = Date.now(); console.log('this.timeStampRef', this.timeStampRef); return /*#__PURE__*/React__default.createElement(Freeze, { freeze: autoFreeze && freeze }, /*#__PURE__*/React__default.createElement("div", { ref: function ref(node) { _this4.wrapper = node; } }, /*#__PURE__*/React__default.createElement("div", _extends({}, contentProps, { // key='keeper-container' // nodeKeyIgnore className: "ka-content ".concat(contentProps.className || '') }), /*#__PURE__*/React__default.createElement("div", { ref: function ref(node) { _this4.timeStampRef = node; } }, "\u65F6\u95F4\u6233\uFF1A", timeStamp), React__default.Children.map(children, function (child, idx) { return ( // React.cloneElement(child, { // key: `${child.key || ''}:${key}:${idx}`, // }) child ); })))); } }]); }(React.PureComponent); var _excluded$3 = ["children"]; 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); } }); }); _defineProperty(_this, "keep", function (id, params) { return new Promise(function (resolve) { _this.update(id, _objectSpread2({ id: id }, params)).then(function () { resolve(_this.store.get(id)); }); }); }); _defineProperty(_this, "getCachingNodesByName", function (name) { return _this.getCachingNodes().filter(function (node) { return isRegExp(name) ? name.test(node.name) : node.name === name; }); }); _defineProperty(_this, "getScopeIds", function (ids) { // 递归采集 scope alive nodes id var _getCachingNodesId = function getCachingNodesId(id) { var aliveNodesId = _get(_this.getCache(id), 'aliveNodesId', []); if (aliveNodesId.size > 0) { return [id, _toConsumableArray(aliveNodesId).map(_getCachingNodesId)]; } return [id].concat(_toConsumableArray(aliveNodesId)); }; return _flatten(ids.map(function (id) { return _getCachingNodesId(id); })); }); _defineProperty(_this, "dropById", function (id) { var _this2; for (var _len2 = arguments.length, rest = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { rest[_key2 - 1] = arguments[_key2]; } return (_this2 = _this).handleNodes.apply(_this2, [[id], HANDLE_TYPE_DROP].concat(rest)); }); _defineProperty(_this, "dropScopeByIds", function (ids) { var _this3; for (var _len3 = arguments.length, rest = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { rest[_key3 - 1] = arguments[_key3]; } return (_this3 = _this).handleNodes.apply(_this3, [_this.getScopeIds(ids), HANDLE_TYPE_DROP].concat(rest)); }); _defineProperty(_this, "drop", function (name) { var _this4; for (var _len4 = arguments.length, rest = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { rest[_key4 - 1] = arguments[_key4]; } return (_this4 = _this).handleNodes.apply(_this4, [_this.getCachingNodesByName(name).map(function (node) { return node.id; }), HANDLE_TYPE_DROP].concat(rest)); }); _defineProperty(_this, "dropScope", function (name) { var _this5; for (var _len5 = arguments.length, rest = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) { rest[_key5 - 1] = arguments[_key5]; } return (_this5 = _this).dropScopeByIds.apply(_this5, [_this.getCachingNodesByName(name).map(function (_ref) { var id = _ref.id; return id; })].concat(rest)); }); _defineProperty(_this, "refreshById", function (id) { var _this6; for (var _len6 = arguments.length, rest = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) { rest[_key6 - 1] = arguments[_key6]; } return (_this6 = _this).handleNodes.apply(_this6, [[id], HANDLE_TYPE_REFRESH].concat(rest)); }); _defineProperty(_this, "refreshScopeByIds", function (ids) { var _this7; for (var _len7 = arguments.length, rest = new Array(_len7 > 1 ? _len7 - 1 : 0), _key7 = 1; _key7 < _len7; _key7++) { rest[_key7 - 1] = arguments[_key7]; } return (_this7 = _this).handleNodes.apply(_this7, [_this.getScopeIds(ids), HANDLE_TYPE_REFRESH].concat(rest)); }); _defineProperty(_this, "refresh", function (name) { var _this8; for (var _len8 = arguments.length, rest = new Array(_len8 > 1 ? _len8 - 1 : 0), _key8 = 1; _key8 < _len8; _key8++) { rest[_key8 - 1] = arguments[_key8]; } return (_this8 = _this).handleNodes.apply(_this8, [_this.getCachingNodesByName(name).map(function (node) { return node.id; }), HANDLE_TYPE_REFRESH].concat(rest)); }); _defineProperty(_this, "refreshScope", function (name) { var _this9; for (var _len9 = arguments.length, rest = new Array(_len9 > 1 ? _len9 - 1 : 0), _key9 = 1; _key9 < _len9; _key9++) { rest[_key9 - 1] = arguments[_key9]; } return (_this9 = _this).refreshScopeByIds.apply(_this9, [_this.getCachingNodesByName(name).map(function (_ref2) { var id = _ref2.id; return id; })].concat(rest)); }); _defineProperty(_this, "handleNodes", function (nodesId) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : HANDLE_TYPE_DROP; for (var _len10 = arguments.length, rest = new Array(_len10 > 2 ? _len10 - 2 : 0), _key10 = 2; _key10 < _len10; _key10++) { rest[_key10 - 2] = arguments[_key10]; } return new Promise(function (resolve) { var handleKeepers = []; nodesId.forEach(function (id) { var cache = _this.store.get(id); if (!cache) { return; } var keeper = _this.keepers.get(id); handleKeepers.push(keeper); }); if (handleKeepers.length === 0) { resolve(false); return; } Promise.all(handleKeepers.map(function (keeper) { return _run.apply(void 0, [keeper, type].concat(rest)); })).then(function (responses) { return resolve(responses.every(Boolean)); }); }); }); _defineProperty(_this, "clear", function () { var _this10; for (var _len11 = arguments.length, rest = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { rest[_key11] = arguments[_key11]; } return (_this10 = _this).handleNodes.apply(_this10, [_this.getCachingNodes().map(function (_ref3) { var id = _ref3.id; return id; }), HANDLE_TYPE_DROP].concat(rest)); }); _defineProperty(_this, "getCache", function (id) { return _this.store.get(id); }); _defineProperty(_this, "getNode", function (id) { return _this.nodes.get(id); }); _defineProperty(_this, "getCachingNodes", function () { return _toConsumableArray(_this.nodes.values()); }); // 静态化节点上下文内容,防止重复渲染 _defineProperty(_this, "helpers", { keep: _this.keep, update: _this.update, drop: _this.drop, dropScope: _this.dropScope, dropById: _this.dropById, dropScopeByIds: _this.dropScopeByIds, refresh: _this.refresh, refreshScope: _this.refreshScope, refreshById: _this.refreshById, refreshScopeByIds: _this.refreshScopeByIds, getScopeIds: _this.getScopeIds, clear: _this.clear, getCache: _this.getCache, getNode: _this.getNode, getCachingNodes: _this.getCachingNodes }); return _this; } _inherits(AliveScope, _Component); return _createClass(AliveScope, [{ key: "render", value: function render() { var _this11 = this; var _this$props$children = this.props.children, children = _this$props$children === void 0 ? null : _this$props$children; return /*#__PURE__*/React__default.createElement(AliveScopeProvider$1, { value: this.helpers }, children, /*#__PURE__*/React__default.createElement("div", { style: { display: 'none' } }, _toConsumableArray(this.nodes.values()).map(function (_ref4) { var children = _ref4.children, props = _objectWithoutProperties(_ref4, _excluded$3); return /*#__PURE__*/React__default.createElement(Keeper // key={props.id} , _extends({}, props, { nodes: _this11.nodes.values(), scope: _this11, store: _this11.store, keepers: _this11.keepers, ref: function ref(keeper) { _this11.keepers.set(props.id, keeper); } }), children); }))); } }]); }(React.Component); var _excluded$4 = ["id"], _excluded2 = ["id"], _excluded3 = ["forwardedRef"], _excluded4 = ["forwardedRef"]; function controllerCherryPick(controller) { var drop = controller.drop, dropScope = controller.dropScope, refresh = controller.refresh, refreshScope = controller.refreshScope, clear = controller.clear, getCachingNodes = controller.getCachingNodes; return { drop: drop, dropScope: dropScope, refresh: refresh, refreshScope: refreshScope, clear: clear, getCachingNodes: getCachingNodes }; } var expandKeepAlive = function expandKeepAlive(KeepAlive) { var renderContent = function renderContent(_ref) { var idPrefix = _ref.idPrefix, helpers = _ref.helpers, props = _ref.props; var isOutsideAliveScope = _isUndefined(helpers); if (isOutsideAliveScope) { console.error('You should not use <KeepAlive /> outside a <AliveScope>'); } return isOutsideAliveScope ? _get(props, 'children', null) : /*#__PURE__*/React__default.createElement(NodeKey, { prefix: idPrefix, key: props._nk, manualKey: props.cacheKey }, function (nkId) { var id = props.cacheKey || nkId; return /*#__PURE__*/React__default.createElement(Acceptor, { key: id, id: id }, function (bridgeProps) { return /*#__PURE__*/React__default.createElement(KeepAlive, _extends({ key: id }, props, bridgeProps, { id: id, _helpers: helpers })); }); }); }; var HookExpand = function HookExpand(_ref2) { var idPrefix = _ref2.id, props = _objectWithoutProperties(_ref2, _excluded$4); return renderContent({ idPrefix: idPrefix, helpers: useScopeContext(), props: props }); }; var WithExpand = function WithExpand(_ref3) { var idPrefix = _ref3.id, props = _objectWithoutProperties(_ref3, _excluded2); return /*#__PURE__*/React__default.createElement(AliveScopeConsumer$1, null, function (helpers) { return renderContent({ idPrefix: idPrefix, helpers: helpers, props: props }); }); }; return _isFunction(React.useContext) ? HookExpand : WithExpand; }; var withAliveScope = function withAliveScope(WrappedComponent) { var renderContent = function renderContent(_ref4) { var helpers = _ref4.helpers, props = _ref4.props, forwardedRef = _ref4.forwardedRef; return /*#__PURE__*/React__default.createElement(WrappedComponent, _extends({}, props, helpers, { ref: forwardedRef })); }; var HookScope = function HookScope(_ref5) { var forwardedRef = _ref5.forwardedRef, props = _objectWithoutProperties(_ref5, _excluded3); return renderContent({ helpers: controllerCherryPick(useScopeContext() || {}), props: props, forwardedRef: forwardedRef }); }; var WithScope = function WithScope(_ref6) { var forwardedRef = _ref6.forwardedRef, props = _objectWithoutProperties(_ref6, _excluded4); return /*#__PURE__*/React__default.createElement(AliveScopeConsumer$1, null, function () { var controller = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return renderContent({ helpers: controllerCherryPick(controller), props: props, forwardedRef: forwardedRef }); }); }; var HOCWithAliveScope = _isFunction(React.useContext) ? HookScope : WithScope; if (_isFunction(React.forwardRef)) { var ForwardedRefHOC = /*#__PURE__*/React.forwardRef(function (props, ref) { return /*#__PURE__*/React__default.createElement(HOCWithAliveScope, _extends({}, props, { forwardedRef: ref })); }); return hoistStatics(ForwardedRefHOC, WrappedComponent); } else { return hoistStatics(HOCWithAliveScope, WrappedComponent); } }; var useAliveController = function useAliveController() { if (!_isFunction(React.useContext)) { return {}; } var ctxValue = useScopeContext(); if (!ctxValue) { return {}; } return controllerCherryPick(ctxValue); }; function isScrollableNode() { var node = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (!_isExist(