利用高阶组件解耦
2024-01-10 本文已影响0人
小冰山口
当遇到一个需求, 很常见, 就是在页面添加一个floatingButton
比如:
image.png
这个➕按钮, 其实本身, 以及点击事件.
无论是UI
还是逻辑, 其实跟这个个人简介
这个界面, 并没有什么关系, 它只是刚好在这个界面而已, 这个➕按钮可以出现在其他任何别的界面.
那么问题来了, 如果你要写这样一个在底脚显示➕按钮的界面, 你会怎么写呢?
RN
中有一个很好的解决方案, 就是利用高阶组件
那什么是高阶组件呢? 高阶组件通俗点来说, 就是参数一个组件, 返回值也是一个组件
第一步, 编写一个高阶组件需要遵守一个命名规则, 就是with
开头:
文件名 -> withFloatingButton.tsx
export default (OriginView) => {
return null
}
那如何做到
高阶组件通俗点来说, 就是参数一个组件, 返回值也是一个组件
呢?
这时候需要定义一个泛型
type IReactComponents =
React.ComponentClass |
React.FunctionComponent |
React.ClassicComponentClass |
React.ForwardRefExoticComponent<any>
export default<T extends IReactComponents> (OriginView: T): T => {
return null
}
定义泛型之后, 再定义一个要返回的HOC
组件
import React from 'react'
type IReactComponents =
React.ComponentClass |
React.FunctionComponent |
React.ClassicComponentClass |
React.ForwardRefExoticComponent<any>
export default<T extends IReactComponents> (OriginView: T): T => {
const HOCView = (props: any) => {
return (
<>
</>
)
}
return HOCView as T
}
然后再将传进来的参数组件和floatingButton
进行"组合", 作为一个result
组件, 返回出去
import React from 'react'
import { TouchableOpacity, StyleSheet, Image } from 'react-native'
type IReactComponents =
React.ComponentClass |
React.FunctionComponent |
React.ClassicComponentClass |
React.ForwardRefExoticComponent<any>
const addButton = require('../assets/images/icon_add.png')
export default<T extends IReactComponents> (OriginView: T): T => {
const HOCView = (props: any) => {
return (
<>
<OriginView {...props}>
</OriginView>
<TouchableOpacity
style={styles.addButton}
onPress={() => {
console.log('点击了一个➕按钮')
}}
>
<Image
source={addButton}
style={styles.addImage}
>
</Image>
</TouchableOpacity>
</>
)
}
return HOCView as T
}
const styles = StyleSheet.create({
addButton: {
position: 'absolute',
bottom: 64,
right: 28
},
addImage: {
width: 54,
height: 54
}
})
以上, 这个组件就写好了, 怎么使用呢?
只需要在你需要添加这个floatingButton
的这个界面的函数外面套上withFloatingButton
这个组件就好了
比如以前的函数是
default () => {
return (
<... .../>
)
}
那现在只需要把default
后面的那个函数组件, 当做参数传到withFloatingButton
中就行了, 因为withFloatingButton
的返回值也是一个函数组件
原来的:
export default () => {
const theme = useContext(ThemeContext)
const styles = theme === 'dark' ? darkStyles : lightStyles
return (
<View style={styles.avarta}>
<Image
style={styles.img}
source={icon_avatar}
>
</Image>
<Text style={styles.titleTxt}>
{`个人信息介绍`}
</Text>
<View style={styles.descContent}>
<Text style={styles.descTxt}>
{`为你阿斯蒂芬金阿奎放假啊收垃圾饭卡激发;卡结算单付款了;阿基德首付款垃圾啊读书卡拉法基阿萨法`}
</Text>
</View>
</View>
)
}
添加了floatingButton
后的:
export default withFloatingButton(
() => {
const theme = useContext(ThemeContext)
const styles = theme === 'dark' ? darkStyles : lightStyles
return (
<View style={styles.avarta}>
<Image
style={styles.img}
source={icon_avatar}
>
</Image>
<Text style={styles.titleTxt}>
{`个人信息介绍`}
</Text>
<View style={styles.descContent}>
<Text style={styles.descTxt}>
{`为你阿斯蒂芬金阿奎放假啊收垃圾饭卡激发;卡结算单付款了;阿基德首付款垃圾啊读书卡拉法基阿萨法`}
</Text>
</View>
</View>
)
}
)
这样, 一个简单的高阶组件就写好了