From 4301049553b6c0207e553bbf8c0f6bad673afb5d Mon Sep 17 00:00:00 2001 From: CJY <375564567@qq.com> Date: Mon, 11 Nov 2019 11:19:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20AliveScope=20=E5=A4=96?= =?UTF-8?q?=E9=83=A8=E5=91=8A=E8=AD=A6=EF=BC=9B=E4=BF=AE=E5=A4=8D=20saveSc?= =?UTF-8?q?rollPosition=20=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98=EF=BC=88?= =?UTF-8?q?=E7=BC=BA=E5=A4=B1=20value=20=E5=87=BD=E6=95=B0=EF=BC=89?= =?UTF-8?q?=EF=BC=9B=E4=BF=AE=E5=A4=8D=20saveScrollPosition=20=E5=AF=B9?= =?UTF-8?q?=E5=B1=8F=E5=B9=95=E6=BB=9A=E5=8A=A8=E5=85=83=E7=B4=A0=E7=9A=84?= =?UTF-8?q?=E4=B8=8D=E6=A0=87=E5=87=86=E6=8E=A2=E6=B5=8B=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=EF=BC=9BKeepAlive=20=E7=9E=AC=E6=97=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=94=81=E5=91=8A=E8=AD=A6=E6=9B=BF=E6=8D=A2=E4=B8=BA=E8=8B=B1?= =?UTF-8?q?=E6=96=87=EF=BC=8C=E4=B8=8E=E4=B8=96=E7=95=8C=E6=8E=A5=E8=BD=A8?= =?UTF-8?q?=EF=BC=9B=E6=9B=B4=E6=96=B0=20README=EF=BC=8C=E8=AF=B4=E6=98=8E?= =?UTF-8?q?=20AliveScope=20=E4=BD=BF=E7=94=A8=E6=96=B9=E5=BC=8F=E4=B8=8E?= =?UTF-8?q?=E6=B3=A8=E6=84=8F=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 71 ++++++++++++++++------------- README_CN.md | 74 +++++++++++++++++-------------- package.json | 2 +- src/core/KeepAlive.js | 6 +-- src/core/withAliveScope.js | 40 ++++++++++++----- src/helpers/base/try/index.js | 6 +++ src/helpers/saveScrollPosition.js | 9 ++-- 7 files changed, 124 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 5cd4977..be24933 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,9 @@ npm install react-activation ## Usage -Add `react-activation/babel` plugins in `.babelrc` +#### 1. Add `react-activation/babel` plugins in `.babelrc` -The plugin adds a `_ka` attribute to each JSX element during compilation to help the `` runtime generate a unique identifier by render location. +The plugin adds a `_ka` attribute to each JSX element during compilation to help the `react-activation` runtime **generate an unique identifier by render location**. ```javascript { @@ -52,57 +52,64 @@ The plugin adds a `_ka` attribute to each JSX element during compilation to help } ``` -In your business code +#### 2. In your business code, place the `` outer layer at a location that will not be unmounted, usually at the application entrance + +Note: When used with `react-router` or `react-redux`, you need to place `` inside `` or `` ```javascript -import React, { Component, useState } from 'react' +// entry.js + +import React from 'react' import ReactDOM from 'react-dom' -import KeepAlive, { AliveScope, withActivation } from 'react-activation' +import { AliveScope } from 'react-activation' -@withActivation -class Test extends Component { - state = { - count: 0 - } +import Test from './Test' - setCount = count => this.setState({ count }) +ReactDOM.render( + + + , + document.getElementById('root') +) +``` - componentDidActivate() { - console.log('Test: componentDidActivate') - } +#### 3. Wrap the components that need to keep states with `` - componentWillUnactivate() { - console.log('Test: componentWillUnactivate') - } +Like the `` component in the example - render() { - const { count } = this.state - - return ( -
- count: {count} - -
- ) - } +```javascript +// Test.js + +import React, { useState } from 'react' +import KeepAlive from 'react-activation' + +function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

count: {count}

+ +
+ ) } -function App() { +function Test() { const [show, setShow] = useState(true) return ( - +
{show && ( )} - +
) } -ReactDOM.render(, document.getElementById('root')) +export default Test ``` - - - @@ -117,7 +124,7 @@ Use `componentDidActivate` and `componentWillUnactivate` to correspond to the tw ```javascript ... -import KeepAlive, { useActivate, useUnactivate, withActivation } from 'react-activation' +import KeepAlive, { useActivate, useUnactivate, withActivation } from 'react-activation' @withActivation class TestClass extends Component { diff --git a/README_CN.md b/README_CN.md index d688644..da74e44 100644 --- a/README_CN.md +++ b/README_CN.md @@ -33,16 +33,17 @@ Vue 中 `` 功能在 React 中的实现 ```bash yarn add react-activation -# or +# 或者 npm install react-activation ``` + - - - ## 使用方式 -`.babelrc` 中增加 `react-activation/babel` 插件 +#### 1. babel 配置文件 `.babelrc` 中增加 `react-activation/babel` 插件 -该插件会于编译阶段在各 JSX 元素上增加 `_ka` 属性,帮助 KeepAlive 运行时按渲染位置生成唯一的缓存 id 标识 +该插件会于编译阶段在各 JSX 元素上增加 `_ka` 属性,帮助 `react-activation` 在运行时**按渲染位置生成唯一的缓存 id 标识** ```javascript { @@ -52,57 +53,64 @@ npm install react-activation } ``` -业务代码中 +#### 2. 业务代码中,在不会被销毁的位置放置 `` 外层,一般为应用入口处 + +注意:与 `react-router` 或 `react-redux` 配合使用时,需要将 `` 放置在 `` 或 `` 内部 ```javascript -import React, { Component, useState } from 'react' +// entry.js + +import React from 'react' import ReactDOM from 'react-dom' -import KeepAlive, { AliveScope, withActivation } from 'react-activation' +import { AliveScope } from 'react-activation' -@withActivation -class Test extends Component { - state = { - count: 0 - } +import Test from './Test' - setCount = count => this.setState({ count }) +ReactDOM.render( + + + , + document.getElementById('root') +) +``` - componentDidActivate() { - console.log('Test: componentDidActivate') - } +#### 3. 用 `` 包裹需要保持状态的组件 - componentWillUnactivate() { - console.log('Test: componentWillUnactivate') - } +如例子中的 `` 组件 - render() { - const { count } = this.state - - return ( -
- count: {count} - -
- ) - } +```javascript +// Test.js + +import React, { useState } from 'react' +import KeepAlive from 'react-activation' + +function Counter() { + const [count, setCount] = useState(0) + + return ( +
+

count: {count}

+ +
+ ) } -function App() { +function Test() { const [show, setShow] = useState(true) return ( - +
{show && ( )} - +
) } -ReactDOM.render(, document.getElementById('root')) +export default Test ``` - - - @@ -117,7 +125,7 @@ ReactDOM.render(, document.getElementById('root')) ```javascript ... -import KeepAlive, { useActivate, useUnactivate, withActivation } from 'react-activation' +import KeepAlive, { useActivate, useUnactivate, withActivation } from 'react-activation' @withActivation class TestClass extends Component { diff --git a/package.json b/package.json index fa60409..a0e6828 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-activation", - "version": "0.3.1", + "version": "0.3.2", "description": " for React like in vue", "main": "index.js", "scripts": { diff --git a/src/core/KeepAlive.js b/src/core/KeepAlive.js index e3c3680..2cdb298 100644 --- a/src/core/KeepAlive.js +++ b/src/core/KeepAlive.js @@ -21,9 +21,9 @@ import saveScrollPosition from '../helpers/saveScrollPosition' const getErrorTips = name => ` 瞬时更新次数过多,可能遇到了更新的死循环,已强制暂停更新 -您现在可见的更新结果存在严重的性能问题 -可能遇到了隐含的 bug,请不要使用 KeepAlive 并联系作者解决` + }/> Too many transient updates, may have encountered an infinite loop of updates, forced to pause the update +There are serious performance issues with the update results you are currently seeing +May encounter an implied bug, please don't use KeepAlive and contact the author to solve` const parseWhenResult = res => { if (isArray(res)) { diff --git a/src/core/withAliveScope.js b/src/core/withAliveScope.js index 9c7d53c..b40e206 100644 --- a/src/core/withAliveScope.js +++ b/src/core/withAliveScope.js @@ -1,7 +1,7 @@ import React, { forwardRef, useContext } from 'react' import hoistStatics from 'hoist-non-react-statics' -import { isFunction } from '../helpers' +import { get, isFunction, isUndefined } from '../helpers' import { Acceptor } from './Bridge' import AliveIdProvider from './AliveIdProvider' @@ -13,17 +13,33 @@ function controllerCherryPick(controller) { } export const expandKeepAlive = KeepAlive => { - const renderContent = ({ idPrefix, helpers, props }) => ( - - {id => ( - - {bridgeProps => ( - - )} - - )} - - ) + const renderContent = ({ idPrefix, helpers, props }) => { + const isOutsideAliveScope = isUndefined(helpers) + + if (isOutsideAliveScope) { + console.error('You should not use outside a ') + } + + return isOutsideAliveScope ? ( + get(props, 'children', null) + ) : ( + + {id => ( + + {bridgeProps => ( + + )} + + )} + + ) + } const HookExpand = ({ id: idPrefix, ...props }) => renderContent({ idPrefix, helpers: useContext(aliveScopeContext), props }) diff --git a/src/helpers/base/try/index.js b/src/helpers/base/try/index.js index 80d1c2a..d4a2b0d 100644 --- a/src/helpers/base/try/index.js +++ b/src/helpers/base/try/index.js @@ -23,3 +23,9 @@ export const run = (obj, keys = [], ...args) => { return isFunction(func) ? func.call(context, ...args) : func } + +export const value = (...values) => + values.reduce( + (value, nextValue) => (isUndefined(value) ? run(nextValue) : run(value)), + undefined + ) diff --git a/src/helpers/saveScrollPosition.js b/src/helpers/saveScrollPosition.js index 9395977..44c484a 100644 --- a/src/helpers/saveScrollPosition.js +++ b/src/helpers/saveScrollPosition.js @@ -4,6 +4,11 @@ import { isArray, isFunction, isExist } from './base/is' import { flatten } from './utils' const body = get(root, 'document.body') +const screenScrollingElement = get( + root, + 'document.scrollingElement', + get(root, 'document.documentElement', {}) +) function isScrollableNode(node = {}) { if (!isExist(node)) { @@ -30,9 +35,7 @@ export default function saveScrollPosition(from, screenInclude) { ...new Set([ ...flatten((!isArray(from) ? [from] : from).map(getScrollableNodes)), ...(screenInclude - ? [get(root, 'document.documentElement', {}), body].filter( - isScrollableNode - ) + ? [screenScrollingElement, body].filter(isScrollableNode) : []) ]) ]