模板版本:v0.3.0
react-native-root-siblings
[! TIP] Github address
请到三方库的 Releases发布地址查看配套的版本信息:
| 三方库版本 | 支持RN版本 |
|---|---|
| 5.0.1 | 0.72/0.77 |
对于未发布到npm的旧版本,请参考安装指南安装tgz包。
安装与使用
进入到工程目录并输入以下命令:
npm
npm i react-native-root-siblings@5.0.1
yarn
yarn add react-native-root-siblings@5.0.1
下面的代码展示了这个库的基本使用场景:
[! WARNING] 使用时 import 的库名不变。
为 React 和 React-native 创建叠加层(Modal、Popover、Dialog 等)的最简单方法。
创建您自己的 showModal 并在任何组件中使用它,无需任何 isShow 状态,甚至可以在纯函数调用中使用它。
import RootSiblingsManager from 'react-native-root-siblings';
import React from 'react';
import { View, Text, Button } from 'react-native';
export const showModal = (renderModal) => {
let rootNode;
const onClose = () => {
rootNode?.destroy();
rootNode = null;
};
rootNode = new RootSiblingsManager(renderModal(onClose));
return onClose;
};
const WelcomeModal = ({ onClose }) => {
return (
<View>
<Text>Welcome!</Text>
<Text>Thanks for using out app!</Text>
<Button title="Close" onPress={onClose}/>
</View>
)
};
export function showWelcomeModal() {
showModal((onClose) => <WelcomeModal onClose={onClose} />);
}
// ...
function HomeScreen() {
return <Button onClick={showWelcomeModal}>Welcome!</Button>
}
setTimeout(showWelcomeModal, 3000);
在根渲染函数中,在组件和根应用程序之间插入“RootSiblingParent”。
import { RootSiblingParent } from 'react-native-root-siblings';
return (
<SomeProviders>
<RootSiblingParent> // <- use RootSiblingParent to wrap your root component
<App />
</RootSiblingParent>
</SomeProviders>
);
RootSiblingParent 充当挂载基座,可以多次挂载。只有最后挂载的那个才会处于活动状态。
在 React Native 中,视图越靠近根级别,其层次结构就越高。
<RootSiblingParent>
<RootView> // <- the highest view
<NavigationView>
<ScreenView> // <- the lowest view
{ /* what if you want to show a fullscreen modal here?
* usually you have to use a Native Modal which is even higher than RootView
* but it's buggy and has a lot of limitations
*/}
<RootSiblingPortal>
{ /* View put in here would be transported to RootSiblingParent
* So it can have a same hierarchy as the RootView to cover any other views
*/}
<View>
</View>
</RootSiblingPortal>
</ScreenView>
</NavigationView>
</RootView>
</RootSiblingParent>
在 React 中,有 createPortal,但它仍然不太方便,因为它不能在组件外部使用。
react-native-root-siblings 提供了最大的灵活性:
Imperative API
- Create sibling element
let sibling = new RootSiblings(<View
style={{top: 0,right: 0,bottom: 0,left: 0,backgroundColor: 'red'}}
/>);
创建一个覆盖所有应用元素的 View 元素,并返回一个同级实例。 可以在任何位置创建同级实例,无论是在组件、钩子中,还是在纯函数中。
- Update sibling element
sibling.update(<View
style={{top: 10,right: 10,bottom: 10,left: 10,backgroundColor: 'blue'}}
/>);
将同级实例更新为具有蓝色背景颜色的视图,并覆盖屏幕“10”偏移距离。
- Destroy sibling element
sibling.destroy();
删除同级元素。
组件 API
import { RootSiblingPortal } from 'react-native-root-siblings';
class extends Component {
render() {
return (
<RootSiblingPortal>
<View style={[StyleSheet.absoluteFill, { backgroundColor: 'rgba(0, 0, 0, 0.25)' }]} />
</RootSiblingPortal>
)
}
}
使用示例
import React, {
AppRegistry,
View,
Component,
TouchableHighlight,
StyleSheet,
Text
} from 'react-native';
import Dimensions from 'Dimensions';
// Import library there,it will wrap everything registered by AppRegistry.registerComponent
// And add or remove other elements after the root component
import RootSiblings from 'react-native-root-siblings';
var id = 0;
var elements = [];
class SiblingsExample extends Component{
addSibling = () => {
let sibling = new RootSiblings(<View
style={[styles.sibling, {top: id * 20}]}
>
<Text>I`m No.{id}</Text>
</View>);
id++;
elements.push(sibling);
};
destroySibling = () => {
let lastSibling = elements.pop();
lastSibling && lastSibling.destroy();
};
updateSibling = () => {
let lastId = elements.length - 1;
lastId >= 0 && elements[lastId].update(<View
style={[styles.sibling, {top: lastId * 20}]}
>
<Text>I`m No.{lastId} : {Math.random()}</Text>
</View>);
};
render() {
return <View style={styles.container}>
<TouchableHighlight
style={styles.button}
onPress={this.addSibling}
>
<Text style={styles.buttonText}>Add element</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.button}
onPress={this.destroySibling}
>
<Text style={styles.buttonText}>Destroy element</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.button}
onPress={this.updateSibling}
>
<Text style={styles.buttonText}>Update element</Text>
</TouchableHighlight>
</View>;
}
}
AppRegistry.registerComponent('SiblingsExample', () => SiblingsExample);
var styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'green',
},
button: {
borderRadius: 4,
padding: 10,
marginLeft: 10,
marginRight: 10,
backgroundColor: '#ccc',
borderColor: '#333',
borderWidth: 1,
},
buttonText: {
color: '#000'
},
sibling: {
left: 0,
height: 20,
width: Dimensions.get('window').width / 2,
backgroundColor: 'blue',
opacity: 0.5
}
});
约束与限制
兼容性
本文档内容基于以下版本验证通过:
- RNOH: 0.72.23; SDK: HarmonyOS NEXT Developer Beta1; IDE: DevEco Studio: 5.0.3.27; ROM: 3.0.0.19;
- RNOH:0.72.33; SDK:OpenHarmony 5.0.0.71(API Version 12 Release); IDE:DevEco Studio 5.0.3.900; ROM:NEXT.0.0.71;
- RNOH: 0.77.18; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.868; ROM: 6.0.0.112;
静态方法
"Platform"列表示该属性在原三方库上支持的平台。
"HarmonyOS Support"列为 yes 表示 HarmonyOS 平台支持该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
| Name | Description | Type | Required | Platform | HarmonyOS Support |
|---|---|---|---|---|---|
| RootSiblings(element: ReactElement, options?: Options) | 创建一个新的兄弟元素 | RootSiblings | no | Android/IOS | yes |
| RootSiblings.update(element: ReactNode, callback?: () => void) | 更新兄弟元素内容 | void | no | Android/IOS | yes |
| RootSiblings.destroy(callback?: () => void) | 销毁兄弟元素 | void | no | Android/IOS | yes |
| RootSiblingParent(props: {children: ReactNode; inactive?: boolean;}) | 包裹需要创建和管理的根级组件 | import("react/jsx-runtime").JSX.Element | no | Android/IOS | yes |
| RootSiblingPortal(props: { children: ReactNode;}) | 允许将子组件渲染到应用的根组件之外的任意位置 | null | no | Android/IOS | yes |
| setSiblingWrapper(wrapper: (sibling: ReactNode) => ReactNode) | 设置全局组件的包装器 | void | no | Android/IOS | yes |
遗留问题
其他
开源协议
本项目基于 The MIT License (MIT) ,请自由地享受和参与开源。