Skip to content

Commit efc1d66

Browse files
authored
refactor: popup 优化代码 (#2944)
1 parent e0c92d6 commit efc1d66

File tree

3 files changed

+50
-111
lines changed

3 files changed

+50
-111
lines changed

src/packages/popup/doc.taro.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,7 @@ import { Popup } from '@nutui/nutui-react-taro'
135135
| \--nutui-popup-title-height | 标题栏的高度 | `50px` |
136136
| \--nutui-popup-title-border-bottom | 标题栏底部边框 | `0` |
137137
| \--nutui-popup-animation-duration | 弹框动画的延时 | `0.3s` |
138+
139+
## FAQ
140+
141+
在 iOS 下,有时候 `lockScroll` 可能不生效,此刻在打开 `popup` 时,可将宿主页面的样式增加 `overflow: hidden;`,关闭弹层时,再重置样式。

src/packages/popup/popup.taro.tsx

Lines changed: 22 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { createPortal } from 'react-dom'
1010
import { CSSTransition } from 'react-transition-group'
1111
import classNames from 'classnames'
1212
import { Close } from '@nutui/icons-react-taro'
13-
import { EnterHandler, ExitHandler } from 'react-transition-group/Transition'
1413
import { View, ITouchEvent } from '@tarojs/components'
1514
import {
1615
OverlayProps,
@@ -108,34 +107,21 @@ export const Popup: FunctionComponent<
108107
const [transitionName, setTransitionName] = useState('')
109108
const refObject = useLockScrollTaro(innerVisible && lockScroll)
110109
const classPrefix = 'nut-popup'
111-
const baseStyle = {
112-
zIndex: index,
113-
}
114110

115111
const overlayStyles = {
116112
...overlayStyle,
117113
'--nutui-overlay-zIndex': index,
118114
}
119-
120-
const popStyles = {
121-
...style,
122-
...baseStyle,
123-
}
124-
115+
const popStyles = { ...style, zIndex: index }
125116
const popClassName = classNames(
117+
classPrefix,
126118
{
127-
[`${classPrefix}`]: true,
128119
[`${classPrefix}-round`]: round || position === 'bottom',
129120
[`${classPrefix}-${position}`]: true,
130121
},
131122
className
132123
)
133124

134-
const closeClasses = classNames({
135-
[`${classPrefix}-title-right`]: true,
136-
[`${classPrefix}-title-right-${closeIconPosition}`]: true,
137-
})
138-
139125
const open = () => {
140126
if (!innerVisible) {
141127
setInnerVisible(true)
@@ -159,40 +145,26 @@ export const Popup: FunctionComponent<
159145
}
160146
}
161147

162-
const onHandleClickOverlay = (e: ITouchEvent) => {
148+
const handleOverlayClick = (e: ITouchEvent) => {
163149
e.stopPropagation()
164-
if (closeOnOverlayClick) {
165-
const closed = onOverlayClick && onOverlayClick(e)
166-
closed && close()
150+
if (closeOnOverlayClick && onOverlayClick(e)) {
151+
close()
167152
}
168153
}
169154

170-
const onHandleClick = (e: ITouchEvent) => {
171-
onClick && onClick(e)
172-
}
173-
174-
const onHandleClickCloseIcon = (e: ITouchEvent) => {
175-
const closed = onCloseIconClick && onCloseIconClick(e)
176-
closed && close()
177-
}
178-
179-
const onHandleOpened: EnterHandler<HTMLElement | undefined> | undefined = (
180-
e: HTMLElement
181-
) => {
182-
afterShow && afterShow()
183-
}
184-
185-
const onHandleClosed: ExitHandler<HTMLElement | undefined> | undefined = (
186-
e: HTMLElement
187-
) => {
188-
afterClose && afterClose()
155+
const handleCloseIconClick = (e: ITouchEvent) => {
156+
onCloseIconClick(e) && close()
189157
}
190158

191159
const renderCloseIcon = () => {
160+
const closeClasses = classNames(
161+
`${classPrefix}-title-right`,
162+
`${classPrefix}-title-right-${closeIconPosition}`
163+
)
192164
return (
193165
<>
194166
{closeable && (
195-
<View className={closeClasses} onClick={onHandleClickCloseIcon}>
167+
<View className={closeClasses} onClick={handleCloseIconClick}>
196168
{React.isValidElement(closeIcon) ? closeIcon : <Close />}
197169
</View>
198170
)}
@@ -244,18 +216,18 @@ export const Popup: FunctionComponent<
244216
unmountOnExit={destroyOnClose}
245217
timeout={duration}
246218
in={innerVisible}
247-
onEntered={onHandleOpened}
248-
onExited={onHandleClosed}
219+
onEntered={afterShow}
220+
onExited={afterClose}
249221
>
250222
<View
251223
ref={refObject}
252224
style={popStyles}
253225
className={popClassName}
254-
onClick={onHandleClick}
226+
onClick={onClick}
255227
catchMove={lockScroll}
256228
>
257229
{renderTitle()}
258-
{showChildren ? children : ''}
230+
{showChildren ? children : null}
259231
</View>
260232
</CSSTransition>
261233
)
@@ -264,17 +236,17 @@ export const Popup: FunctionComponent<
264236
const renderNode = () => {
265237
return (
266238
<>
267-
{overlay ? (
239+
{overlay && (
268240
<Overlay
269241
style={overlayStyles}
270242
className={overlayClassName}
271243
visible={innerVisible}
272244
closeOnOverlayClick={closeOnOverlayClick}
273245
lockScroll={lockScroll}
274246
duration={duration}
275-
onClick={onHandleClickOverlay}
247+
onClick={handleOverlayClick}
276248
/>
277-
) : null}
249+
)}
278250
{renderPop()}
279251
</>
280252
)
@@ -288,11 +260,9 @@ export const Popup: FunctionComponent<
288260
setTransitionName(transition || `${classPrefix}-slide-${position}`)
289261
}, [position, transition])
290262

291-
const resolveContainer = (getContainer: Teleport | undefined) => {
292-
const container =
293-
typeof getContainer === 'function' ? getContainer() : getContainer
294-
return container || document.body
295-
}
263+
const resolveContainer = (getContainer: Teleport | undefined) =>
264+
(typeof getContainer === 'function' ? getContainer() : getContainer) ||
265+
document.body
296266

297267
const renderToContainer = (getContainer: Teleport, node: ReactElement) => {
298268
if (getContainer) {

src/packages/popup/popup.tsx

Lines changed: 24 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, {
22
FunctionComponent,
33
MouseEvent,
4-
MouseEventHandler,
54
ReactElement,
65
ReactNode,
76
ReactPortal,
@@ -12,7 +11,6 @@ import { createPortal } from 'react-dom'
1211
import { CSSTransition } from 'react-transition-group'
1312
import classNames from 'classnames'
1413
import { Close } from '@nutui/icons-react'
15-
import { EnterHandler, ExitHandler } from 'react-transition-group/Transition'
1614
import { defaultOverlayProps, OverlayProps } from '@/packages/overlay/overlay'
1715
import Overlay from '@/packages/overlay'
1816
import { ComponentDefaults } from '@/utils/typings'
@@ -98,45 +96,30 @@ export const Popup: FunctionComponent<
9896
afterClose,
9997
onClick,
10098
} = { ...defaultProps, ...props }
101-
const nodeRef = React.useRef(null)
99+
const nodeRef = React.useRef<HTMLDivElement | null>(null)
102100
let innerIndex = zIndex || _zIndex
103101
const [index, setIndex] = useState(innerIndex)
104102
const [innerVisible, setInnerVisible] = useState(visible)
105103
const [showChildren, setShowChildren] = useState(true)
106104
const [transitionName, setTransitionName] = useState('')
107105

108-
const shouldLockScroll = !innerVisible ? false : lockScroll
109-
useLockScroll(nodeRef, shouldLockScroll)
106+
useLockScroll(nodeRef, innerVisible && lockScroll)
110107

111108
const classPrefix = 'nut-popup'
112-
const baseStyle = {
113-
zIndex: index,
114-
}
115-
116109
const overlayStyles = {
117110
...overlayStyle,
118111
'--nutui-overlay-zIndex': index,
119112
}
120-
121-
const popStyles = {
122-
...style,
123-
...baseStyle,
124-
}
125-
113+
const popStyles = { ...style, zIndex: index }
126114
const popClassName = classNames(
115+
classPrefix,
127116
{
128-
[`${classPrefix}`]: true,
129117
[`${classPrefix}-round`]: round || position === 'bottom',
130118
[`${classPrefix}-${position}`]: true,
131119
},
132120
className
133121
)
134122

135-
const closeClasses = classNames({
136-
[`${classPrefix}-title-right`]: true,
137-
[`${classPrefix}-title-right-${closeIconPosition}`]: true,
138-
})
139-
140123
const open = () => {
141124
if (!innerVisible) {
142125
setInnerVisible(true)
@@ -160,42 +143,26 @@ export const Popup: FunctionComponent<
160143
}
161144
}
162145

163-
const onHandleClickOverlay = (e: MouseEvent) => {
146+
const handleOverlayClick = (e: MouseEvent) => {
164147
e.stopPropagation()
165-
if (closeOnOverlayClick) {
166-
const closed = onOverlayClick && onOverlayClick(e)
167-
closed && close()
148+
if (closeOnOverlayClick && onOverlayClick(e)) {
149+
close()
168150
}
169151
}
170152

171-
const onHandleClick: MouseEventHandler<HTMLDivElement> = (e: MouseEvent) => {
172-
onClick && onClick(e)
173-
}
174-
175-
const onHandleClickCloseIcon: MouseEventHandler<HTMLDivElement> = (
176-
e: MouseEvent
177-
) => {
178-
const closed = onCloseIconClick && onCloseIconClick(e)
179-
closed && close()
180-
}
181-
182-
const onHandleOpened: EnterHandler<HTMLElement | undefined> | undefined = (
183-
e: HTMLElement
184-
) => {
185-
afterShow && afterShow()
186-
}
187-
188-
const onHandleClosed: ExitHandler<HTMLElement | undefined> | undefined = (
189-
e: HTMLElement
190-
) => {
191-
afterClose && afterClose()
153+
const handleCloseIconClick = (e: MouseEvent) => {
154+
onCloseIconClick(e) && close()
192155
}
193156

194157
const renderCloseIcon = () => {
158+
const closeClasses = classNames(
159+
`${classPrefix}-title-right`,
160+
`${classPrefix}-title-right-${closeIconPosition}`
161+
)
195162
return (
196163
<>
197164
{closeable && (
198-
<div className={closeClasses} onClick={onHandleClickCloseIcon}>
165+
<div className={closeClasses} onClick={handleCloseIconClick}>
199166
{React.isValidElement(closeIcon) ? closeIcon : <Close />}
200167
</div>
201168
)}
@@ -245,17 +212,17 @@ export const Popup: FunctionComponent<
245212
unmountOnExit={destroyOnClose}
246213
timeout={duration}
247214
in={innerVisible}
248-
onEntered={onHandleOpened}
249-
onExited={onHandleClosed}
215+
onEntered={afterShow}
216+
onExited={afterClose}
250217
>
251218
<div
252219
ref={nodeRef}
253220
style={popStyles}
254221
className={popClassName}
255-
onClick={onHandleClick}
222+
onClick={onClick}
256223
>
257224
{renderTitle()}
258-
{showChildren ? children : ''}
225+
{showChildren ? children : null}
259226
</div>
260227
</CSSTransition>
261228
)
@@ -264,17 +231,17 @@ export const Popup: FunctionComponent<
264231
const renderNode = () => {
265232
return (
266233
<>
267-
{overlay ? (
234+
{overlay && (
268235
<Overlay
269236
style={overlayStyles}
270237
className={overlayClassName}
271238
visible={innerVisible}
272239
closeOnOverlayClick={closeOnOverlayClick}
273240
lockScroll={lockScroll}
274241
duration={duration}
275-
onClick={onHandleClickOverlay}
242+
onClick={handleOverlayClick}
276243
/>
277-
) : null}
244+
)}
278245
{renderPop()}
279246
</>
280247
)
@@ -288,11 +255,9 @@ export const Popup: FunctionComponent<
288255
setTransitionName(transition || `${classPrefix}-slide-${position}`)
289256
}, [position, transition])
290257

291-
const resolveContainer = (getContainer: Teleport | undefined) => {
292-
const container =
293-
typeof getContainer === 'function' ? getContainer() : getContainer
294-
return container || document.body
295-
}
258+
const resolveContainer = (getContainer: Teleport | undefined) =>
259+
(typeof getContainer === 'function' ? getContainer() : getContainer) ||
260+
document.body
296261

297262
const renderToContainer = (getContainer: Teleport, node: ReactElement) => {
298263
if (getContainer) {

0 commit comments

Comments
 (0)