Skip to content

Commit

Permalink
feat: #49
Browse files Browse the repository at this point in the history
  • Loading branch information
Wugaoliang committed Jun 16, 2021
1 parent 696bc79 commit c80179c
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 20 deletions.
48 changes: 28 additions & 20 deletions examples/theme/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import Theme, { history } from '../../src/theme'
import _routeConfig from './routes-config'
import { Input, Icon, Select } from '@hi-ui/hiui'

import { KeepAliveProvider } from '../../keep-alive'
// const KeepAliveHome = withKeepAlive(Home, { cacheId: 'Home' })
// const KeepAliveUserList = withKeepAlive(UserList, { cacheId: 'UserList', scroll: true })
// const KeepAliveUserAdd = withKeepAlive(UserAdd, { cacheId: 'UserAdd' })

const logoConfig = {
logoUrl: 'https://xiaomi.github.io/hiui/static/img/logo.png?241e0618fe55d933c280e38954edea05',
name: <span>HIUI Theme</span>,
Expand All @@ -26,6 +31,7 @@ const toolbar = [
<Input key="1" style={{ width: 200 }} />,
<Icon key="2" name="prompt" />,
<Select
key="3"
type="single"
clearable={false}
style={{ width: 200 }}
Expand Down Expand Up @@ -80,26 +86,28 @@ class App extends Component {
// }
render() {
return (
<Theme
// routes={this.state.routeConfig}
routes={_routeConfig}
logo={logoConfig}
// siderTopRender={(mini) => (mini ? <div>X</div> : <div>XData</div>)}
login={loginConfig}
type="classic"
// header={null}
theme={'orange'}
authority={['normal']}
// fallback="/404"
// type='genuine'
apperance={{ color: 'light' }}
// apperance={{ contentBackground: '#fff', contentPadding: 0 }}
accordion={false}
toolbar={toolbar2}
onMenuClick={(item) => {
console.log('item', item)
}}
/>
<KeepAliveProvider>
<Theme
// routes={this.state.routeConfig}
routes={_routeConfig}
logo={logoConfig}
// siderTopRender={(mini) => (mini ? <div>X</div> : <div>XData</div>)}
login={loginConfig}
// type="classic"
// header={null}
theme={'orange'}
authority={['normal']}
// fallback="/404"
type="genuine"
apperance={{ color: 'light' }}
// apperance={{ contentBackground: '#fff', contentPadding: 0 }}
accordion={false}
toolbar={toolbar2}
onMenuClick={(item) => {
console.log('item', item)
}}
/>
</KeepAliveProvider>
)
}
}
Expand Down
26 changes: 26 additions & 0 deletions examples/theme/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react'
import { Select } from '@hi-ui/hiui'
import { Select as AntSelect } from 'antd'

import 'antd/dist/antd.css'

const { Option } = AntSelect
const Page = () => {
return (
<div>
<Select data={[]}></Select>

<h2>四类</h2>
<AntSelect defaultValue="lucy" style={{ width: 120 }}>
<Option value="jack">Jack</Option>
<Option value="lucy">Lucy</Option>
<Option value="disabled" disabled>
Disabled
</Option>
<Option value="Yiminghe">yiminghe</Option>
</AntSelect>
<div style={{ height: '100vh' }}></div>
</div>
)
}
export default Page
9 changes: 9 additions & 0 deletions examples/theme/routes-config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react'
import { Link } from 'react-router-dom'
import Page from './page'
import { withKeepAlive } from '../../keep-alive'

const CC = () => (
<div>
Expand All @@ -23,6 +25,8 @@ const RobotDetail = () => <div>米家扫地机器人详情页</div>
const Iot = () => <div>iot</div>
const XiaoAi = () => <div>xiaoai</div>

const KeepAlivePage = withKeepAlive(Page, { cacheId: 'page' })

const config = [
{
name: '智能硬件',
Expand All @@ -41,6 +45,11 @@ const config = [
{ path: '/robot-detail/:id', component: RobotDetail }
]
},
{
name: '测试popper',
path: '/test-popper',
component: KeepAlivePage
},
{
name: '手机',
children: [
Expand Down
3 changes: 3 additions & 0 deletions keep-alive/CacheContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import React from 'react'
const CacheContext = React.createContext()
export default CacheContext
54 changes: 54 additions & 0 deletions keep-alive/KeepAliveProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useReducer, useCallback } from 'react'
import CacheContext from './CacheContext'
import cacheReducer from './cacheReducer'
import * as cacheTypes from './cache-types'
function KeepAliveProvider(props) {
const [cacheStates, dispatch] = useReducer(cacheReducer, {})
const mount = useCallback(
({ cacheId, element }) => {
if (cacheStates[cacheId]) {
const cacheState = cacheStates[cacheId]
if (cacheState.status === cacheTypes.DESTROY) {
const doms = cacheState.doms
doms.forEach((dom) => dom.parentNode.removeChild(dom))
dispatch({ type: cacheTypes.CREATE, payload: { cacheId, element } })
}
} else {
dispatch({ type: cacheTypes.CREATE, payload: { cacheId, element } })
}
},
[cacheStates]
)
const handleScroll = useCallback(
(cacheId, { target }) => {
if (cacheStates[cacheId]) {
const scrolls = cacheStates[cacheId].scrolls
scrolls[target] = target.scrollTop
}
},
[cacheStates]
)
return (
<CacheContext.Provider value={{ mount, cacheStates, dispatch, handleScroll }}>
{props.children}
{Object.values(cacheStates)
.filter((cacheState) => cacheState.status !== cacheTypes.DESTROY)
.map(({ cacheId, element }) => (
<div
id={`cache_${cacheId}`}
key={cacheId}
ref={(dom) => {
const cacheState = cacheStates[cacheId]
if (dom && (!cacheState.doms || cacheState.status === cacheTypes.DESTROY)) {
const doms = Array.from(dom.childNodes)
dispatch({ type: cacheTypes.CREATED, payload: { cacheId, doms } })
}
}}
>
{element}
</div>
))}
</CacheContext.Provider>
)
}
export default KeepAliveProvider
4 changes: 4 additions & 0 deletions keep-alive/cache-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const CREATE = 'CREATE' // 创建
export const CREATED = 'CREATED' // 创建成功
export const ACTIVE = 'ACTIVE' // 激活
export const DESTROY = 'DESTROY' // 销毁
43 changes: 43 additions & 0 deletions keep-alive/cacheReducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as cacheTypes from './cache-types'
function cacheReducer(cacheStates = {}, { type, payload }) {
switch (type) {
case cacheTypes.CREATE:
return {
...cacheStates,
[payload.cacheId]: {
scrolls: {},
cacheId: payload.cacheId,
element: payload.element,
status: cacheTypes.CREATE
}
}
case cacheTypes.CREATED:
return {
...cacheStates,
[payload.cacheId]: {
...cacheStates[payload.cacheId],
doms: payload.doms,
status: cacheTypes.CREATED
}
}
case cacheTypes.ACTIVE:
return {
...cacheStates,
[payload.cacheId]: {
...cacheStates[payload.cacheId],
status: cacheTypes.ACTIVE
}
}
case cacheTypes.DESTROY:
return {
...cacheStates,
[payload.cacheId]: {
...cacheStates[payload.cacheId],
status: cacheTypes.DESTROY
}
}
default:
return cacheStates
}
}
export default cacheReducer
2 changes: 2 additions & 0 deletions keep-alive/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as KeepAliveProvider } from './KeepAliveProvider'
export { default as withKeepAlive } from './withKeepAlive'
31 changes: 31 additions & 0 deletions keep-alive/withKeepAlive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { useContext, useRef, useEffect } from 'react'
import CacheContext from './CacheContext'
import * as cacheTypes from './cache-types'
const withKeepAlive = (OldComponent, { cacheId = window.location.pathname, scroll = false }) => {
// eslint-disable-next-line react/display-name
return (props) => {
const { mount, cacheStates, dispatch, handleScroll } = useContext(CacheContext)
const ref = useRef(null)
useEffect(() => {
if (scroll) {
ref.current.addEventListener('scroll', handleScroll.bind(null, cacheId), true)
}
}, [handleScroll])
useEffect(() => {
const cacheState = cacheStates[cacheId]
if (cacheState && cacheState.doms && cacheState.status !== cacheTypes.DESTROY) {
const doms = cacheState.doms
doms.forEach((dom) => ref.current.appendChild(dom))
if (scroll) {
doms.forEach((dom) => {
if (cacheState.scrolls[dom]) dom.scrollTop = cacheState.scrolls[dom]
})
}
} else {
mount({ cacheId, element: <OldComponent {...props} dispatch={dispatch} /> })
}
}, [cacheStates, dispatch, mount, props])
return <div id={`keepalive_${cacheId}`} ref={ref} />
}
}
export default withKeepAlive
Empty file added src/keep-alive/context.js
Empty file.

0 comments on commit c80179c

Please sign in to comment.