Skip to content

Commit a64f4ac

Browse files
authored
Merge pull request #516 from nullptr-z/dev
refactor(Drawer): 使用Function组件重构 Class组件
2 parents e207e07 + ec62e01 commit a64f4ac

File tree

1 file changed

+138
-138
lines changed

1 file changed

+138
-138
lines changed

packages/core/src/Drawer/index.tsx

Lines changed: 138 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { Component, Fragment } from 'react';
1+
import React, { Fragment, useEffect, useState } from 'react';
22
import {
33
Animated,
44
StyleSheet,
@@ -32,129 +32,10 @@ export interface DrawerState {
3232
isOpen: boolean;
3333
}
3434

35-
export default class Drawer extends Component<DrawerProps, DrawerState> {
36-
static defaultProps = {
37-
placement: 'left',
38-
drawerBackgroundColor: '#fff',
39-
drawerWidth: 300,
40-
drawerHeight: 500,
41-
maskClosable: true,
42-
isOpen: false,
43-
onChange: () => null,
44-
openDrawer: () => null,
45-
closeDrawer: () => null,
46-
};
47-
constructor(props: DrawerProps) {
48-
super(props);
49-
50-
this.state = {
51-
zIndexValue: 0,
52-
overlayValue: new Animated.Value(0),
53-
drawerValue: new Animated.ValueXY({ ...this.getInitPosition() }),
54-
isOpen: !!props.isOpen,
55-
};
56-
}
57-
handleDrawer = debounce((isOpen: boolean) => {
58-
isOpen ? this.openDrawer() : this.closeDrawer();
59-
}, 100);
60-
61-
componentDidUpdate(prevProps: DrawerProps, prevState: DrawerState) {
62-
if (prevState.isOpen !== this.state.isOpen) {
63-
this.handleDrawer(this.state.isOpen);
64-
}
65-
if (prevProps.isOpen !== this.props.isOpen) {
66-
this.handleDrawer(!!this.props.isOpen);
67-
}
68-
}
69-
componentDidMount() {
70-
if (this.props.isOpen) {
71-
this.openDrawer();
72-
}
73-
}
74-
75-
onOverlayClick = (e: GestureResponderEvent) => {
76-
const { maskClosable } = this.props;
77-
if (!maskClosable) {
78-
return false;
79-
}
80-
e.stopPropagation();
81-
this.closeDrawer();
82-
};
83-
render() {
84-
const { style, drawerWidth, drawerBackgroundColor, maskProps, placement, drawerHeight } = this.props;
85-
const { isOpen, drawerValue, overlayValue, zIndexValue } = this.state;
86-
const isTopOrBottom = placement === 'top' || placement === 'bottom';
87-
const changeStyle = isTopOrBottom ? 'height' : 'width';
88-
const dynamicDrawerStyles: any = {
89-
backgroundColor: drawerBackgroundColor,
90-
};
91-
92-
if (isTopOrBottom) {
93-
dynamicDrawerStyles.top = placement === 'top' ? 0 : null;
94-
dynamicDrawerStyles.bottom = placement === 'bottom' ? 0 : null;
95-
dynamicDrawerStyles.height = drawerWidth;
96-
dynamicDrawerStyles.width = '100%';
97-
} else {
98-
dynamicDrawerStyles.left = placement === 'left' ? 0 : null;
99-
dynamicDrawerStyles.right = placement === 'right' ? 0 : null;
100-
dynamicDrawerStyles.width = drawerWidth;
101-
}
102-
103-
const overlayOpacity = overlayValue.interpolate({
104-
inputRange: [0, 1],
105-
outputRange: [0, 0.3],
106-
extrapolate: 'clamp',
107-
});
108-
return (
109-
<Fragment>
110-
<Animated.View
111-
style={[
112-
styles.drawer,
113-
dynamicDrawerStyles,
114-
style,
115-
// eslint-disable-next-line
116-
{
117-
[changeStyle]: isOpen ? (isTopOrBottom ? drawerHeight : drawerWidth) : 0,
118-
transform: [
119-
{ translateX: drawerValue.x }, // x轴移动
120-
{ translateY: drawerValue.y }, // y轴移动
121-
],
122-
},
123-
]}
124-
>
125-
{this.props.children}
126-
</Animated.View>
127-
<Animated.View
128-
pointerEvents={isOpen ? 'auto' : 'none'}
129-
style={[
130-
styles.overlay,
131-
styles.positionFull,
132-
maskProps,
133-
{
134-
// opacity: overlayValue,
135-
opacity: overlayOpacity,
136-
zIndex: zIndexValue,
137-
},
138-
]}
139-
>
140-
<TouchableOpacity
141-
style={[
142-
styles.positionFull,
143-
// eslint-disable-next-line
144-
{
145-
zIndex: 3003,
146-
position: 'absolute',
147-
},
148-
]}
149-
onPress={this.onOverlayClick.bind(this)}
150-
/>
151-
</Animated.View>
152-
</Fragment>
153-
);
154-
}
155-
156-
getInitPosition() {
157-
const { drawerWidth, placement, drawerHeight } = this.props;
35+
export default function Drawer(props: DrawerProps) {
36+
console.log(333);
37+
const getInitPosition = () => {
38+
const { drawerWidth, placement, drawerHeight } = props;
15839
const xy = { x: 0, y: 0 };
15940
if (placement === 'left') {
16041
xy.x = -(drawerWidth || 0);
@@ -169,30 +50,38 @@ export default class Drawer extends Component<DrawerProps, DrawerState> {
16950
xy.y = DEVICE_HEIGHT || 0;
17051
}
17152
return xy;
172-
}
173-
openDrawer() {
174-
this.setState({ zIndexValue: 3002, isOpen: true });
53+
};
54+
55+
const [state, setState] = useState({
56+
zIndexValue: 0,
57+
overlayValue: new Animated.Value(0),
58+
drawerValue: new Animated.ValueXY({ ...getInitPosition() }),
59+
isOpen: !!props.isOpen,
60+
});
61+
62+
const openDrawer = () => {
63+
setState({ ...state, zIndexValue: 3002, isOpen: true });
17564
Animated.parallel([
176-
Animated.spring(this.state.drawerValue, {
65+
Animated.spring(state.drawerValue, {
17766
toValue: { x: 0, y: 0 },
17867
overshootClamping: true,
17968
useNativeDriver: true,
18069
}),
181-
Animated.spring(this.state.overlayValue, {
70+
Animated.spring(state.overlayValue, {
18271
toValue: 0.7,
18372
overshootClamping: true,
18473
useNativeDriver: true,
18574
}),
18675
]).start(() => {
187-
this.props.openDrawer!(true);
188-
this.props.onChange!(true);
76+
props.openDrawer!(true);
77+
props.onChange!(true);
18978
});
190-
}
191-
closeDrawer() {
192-
const { drawerValue, overlayValue } = this.state;
79+
};
80+
const closeDrawer = () => {
81+
const { drawerValue, overlayValue } = state;
19382
Animated.parallel([
19483
Animated.spring(drawerValue, {
195-
toValue: { ...this.getInitPosition() },
84+
toValue: { ...getInitPosition() },
19685
overshootClamping: true,
19786
useNativeDriver: true,
19887
}),
@@ -202,13 +91,124 @@ export default class Drawer extends Component<DrawerProps, DrawerState> {
20291
useNativeDriver: true,
20392
}),
20493
]).start(() => {
205-
this.props.closeDrawer!(false);
206-
this.props.onChange!(false);
207-
this.setState({ zIndexValue: 0, isOpen: false });
94+
props.closeDrawer!(false);
95+
props.onChange!(false);
96+
setState({ ...state, zIndexValue: 0, isOpen: false });
20897
});
98+
};
99+
100+
const handleDrawer = debounce((isOpen: boolean) => {
101+
isOpen ? openDrawer() : closeDrawer();
102+
}, 100);
103+
104+
useEffect(() => {
105+
handleDrawer(state.isOpen);
106+
}, [state.isOpen]);
107+
108+
useEffect(() => {
109+
handleDrawer(!!props.isOpen);
110+
}, [props.isOpen]);
111+
112+
useEffect(() => {
113+
if (props.isOpen) {
114+
openDrawer();
115+
}
116+
}, []);
117+
118+
const onOverlayClick = (e: GestureResponderEvent) => {
119+
const { maskClosable } = props;
120+
if (!maskClosable) {
121+
return false;
122+
}
123+
e.stopPropagation();
124+
closeDrawer();
125+
};
126+
127+
const { style, drawerWidth, drawerBackgroundColor, maskProps, placement, drawerHeight } = props;
128+
const { isOpen, drawerValue, overlayValue, zIndexValue } = state;
129+
const isTopOrBottom = placement === 'top' || placement === 'bottom';
130+
const changeStyle = isTopOrBottom ? 'height' : 'width';
131+
const dynamicDrawerStyles: any = {
132+
backgroundColor: drawerBackgroundColor,
133+
};
134+
135+
if (isTopOrBottom) {
136+
dynamicDrawerStyles.top = placement === 'top' ? 0 : null;
137+
dynamicDrawerStyles.bottom = placement === 'bottom' ? 0 : null;
138+
dynamicDrawerStyles.height = drawerWidth;
139+
dynamicDrawerStyles.width = '100%';
140+
} else {
141+
dynamicDrawerStyles.left = placement === 'left' ? 0 : null;
142+
dynamicDrawerStyles.right = placement === 'right' ? 0 : null;
143+
dynamicDrawerStyles.width = drawerWidth;
209144
}
145+
146+
const overlayOpacity = overlayValue.interpolate({
147+
inputRange: [0, 1],
148+
outputRange: [0, 0.3],
149+
extrapolate: 'clamp',
150+
});
151+
152+
return (
153+
<Fragment>
154+
<Animated.View
155+
style={[
156+
styles.drawer,
157+
dynamicDrawerStyles,
158+
style,
159+
// eslint-disable-next-line
160+
{
161+
[changeStyle]: isOpen ? (isTopOrBottom ? drawerHeight : drawerWidth) : 0,
162+
transform: [
163+
{ translateX: drawerValue.x }, // x轴移动
164+
{ translateY: drawerValue.y }, // y轴移动
165+
],
166+
},
167+
]}
168+
>
169+
{props.children}
170+
</Animated.View>
171+
<Animated.View
172+
pointerEvents={isOpen ? 'auto' : 'none'}
173+
style={[
174+
styles.overlay,
175+
styles.positionFull,
176+
maskProps,
177+
{
178+
// opacity: overlayValue,
179+
opacity: overlayOpacity,
180+
zIndex: zIndexValue,
181+
},
182+
]}
183+
>
184+
<TouchableOpacity
185+
style={[
186+
styles.positionFull,
187+
// eslint-disable-next-line
188+
{
189+
zIndex: 3003,
190+
position: 'absolute',
191+
},
192+
]}
193+
onPress={onOverlayClick}
194+
/>
195+
</Animated.View>
196+
</Fragment>
197+
);
210198
}
211199

200+
Drawer.defaultProps = {
201+
placement: 'left',
202+
drawerBackgroundColor: '#fff',
203+
drawerWidth: 300,
204+
drawerHeight: 500,
205+
maskClosable: true,
206+
isOpen: false,
207+
onChange: () => null,
208+
openDrawer: () => null,
209+
closeDrawer: () => null,
210+
} as DrawerProps;
211+
212212
const styles = StyleSheet.create({
213213
drawer: {
214214
position: 'absolute',

0 commit comments

Comments
 (0)