返回

React Native中 Modal 实现的正确姿势

前端

前言

在React Native中,我们经常需要使用弹出层组件来实现各种各样的交互场景,比如模态窗口、侧边栏、浮动菜单等等。传统的React Native弹出层组件通常使用绝对定位(absolute positioning)来实现,但这种方式存在一些局限性,比如难以实现跨平台一致的外观和行为、难以处理键盘弹出等。

React Portals

React Portals是一种新的API,它允许我们创建脱离当前组件树的元素,这使得我们可以更轻松地实现弹出层组件。

要使用React Portals,我们需要先创建一个Portal组件,该组件将负责将子元素渲染到一个脱离当前组件树的DOM节点中。

import { Portal } from 'react-native';

const PortalComponent = ({ children }) => {
  return (
    <Portal>
      {children}
    </Portal>
  );
};

然后,我们就可以在其他组件中使用PortalComponent来渲染弹出层组件。

import { PortalComponent } from './PortalComponent';

const MyModal = () => {
  return (
    <PortalComponent>
      <Modal>
        {/* ... */}
      </Modal>
    </PortalComponent>
  );
};

实现弹出层组件

现在,我们就可以开始实现弹出层组件了。

1. 创建一个基本组件

import React, { useState } from 'react';
import { View, Button, Modal } from 'react-native';

const MyModal = () => {
  const [visible, setVisible] = useState(false);

  return (
    <View>
      <Button title="Open Modal" onPress={() => setVisible(true)} />
      <Modal visible={visible} onRequestClose={() => setVisible(false)}>
        {/* ... */}
      </Modal>
    </View>
  );
};

export default MyModal;

2. 添加样式

import React, { useState } from 'react';
import { View, Button, Modal, StyleSheet } from 'react-native';

const MyModal = () => {
  const [visible, setVisible] = useState(false);

  return (
    <View style={styles.container}>
      <Button title="Open Modal" onPress={() => setVisible(true)} />
      <Modal visible={visible} onRequestClose={() => setVisible(false)}>
        {/* ... */}
      </Modal>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default MyModal;

3. 添加内容

import React, { useState } from 'react';
import { View, Button, Modal, StyleSheet, Text } from 'react-native';

const MyModal = () => {
  const [visible, setVisible] = useState(false);

  return (
    <View style={styles.container}>
      <Button title="Open Modal" onPress={() => setVisible(true)} />
      <Modal visible={visible} onRequestClose={() => setVisible(false)}>
        <View style={styles.modalContent}>
          <Text>Hello World!</Text>
        </View>
      </Modal>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  modalContent: {
    backgroundColor: 'white',
    padding: 20,
    borderRadius: 4,
    borderColor: 'rgba(0, 0, 0, 0.1)',
  },
});

export default MyModal;

4. 添加关闭按钮

import React, { useState } from 'react';
import { View, Button, Modal, StyleSheet, Text } from 'react-native';

const MyModal = () => {
  const [visible, setVisible] = useState(false);

  return (
    <View style={styles.container}>
      <Button title="Open Modal" onPress={() => setVisible(true)} />
      <Modal visible={visible} onRequestClose={() => setVisible(false)}>
        <View style={styles.modalContent}>
          <Text>Hello World!</Text>
          <Button title="Close" onPress={() => setVisible(false)} />
        </View>
      </Modal>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  modalContent: {
    backgroundColor: 'white',
    padding: 20,
    borderRadius: 4,
    borderColor: 'rgba(0, 0, 0, 0.1)',
  },
});

export default MyModal;

总结

现在,我们已经成功地实现了一个基本的可用于React Native的Modal弹出层组件。我们可以根据需要对组件进行进一步的定制,以满足我们的具体需求。