利用高阶组件解耦

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>
    )
  }
)

这样, 一个简单的高阶组件就写好了

上一篇下一篇

猜你喜欢

热点阅读