手写|手写 React-Native 方法调用式的 Modal 弹框、Toast 提示
在使用 React-Native 的时候,经常看到一些第三方库的 Modal、Toast 使用方式是这样的:
/** 显示/隐藏 Modal */
Modal.show({/** 做一些快乐的事 */} );
Modal.hide();
/** 显示/隐藏 Toast */
Toast.show('做一些开心的事');
Toast.hide();
那这种弹框在 RN 中是怎么实现的呢?
众所周知,在Web端项目中,实现类似的功能非常之简单:
const modal = document.createElement('div');
modal.style.position = 'fixed';
modal.innerHTML = '做一些快乐的事';
document.body.appendChild(modal);
在 RN 中没有 document 对象,元素也没有 appendChild 方法,该怎么做?
思路:
添加一个根元素的兄弟元素,其样式 “position: absolute, zIndex: 999” ,调用其静态方法使其重新 render 。
实现步骤:
- 创建一个 RootView 组件
/** 定义一个变量用来存储 RootView 实例 */
let rootViewInstance: RootView | undefined;
class RootView extends React.Component {
constructor(props: {}) {
super(props);
rootViewInstance = this;
// 将实例赋值给 rootViewInstance
}public readonly state = {
content: null
};
public static setContent(content) {
rootViewInstance.setState({ content });
}public static clearContent() {
rootViewInstance.setState({ content: null });
}render() {
const { content } = this.state;
return content && (
{content}
);
}
}const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0, left: 0, bottom: 0, right: 0,
zIndex: 999,
flex: 1,
}
});
- 修改项目入口文件,将 RootView 组件添加为根元素的兄弟元素
import { AppRegistry } from 'react-native';
import App from './src/app';
import RootView from '@/components/RootView';
const createRootApp = () => () => (
);
AppRegistry.registerComponent(appName, createRootApp);
- 使用
RootView.setContent(我是一个RootView );
【手写|手写 React-Native 方法调用式的 Modal 弹框、Toast 提示】当然,这样需要修改入口文件,组件的封装性并不好;
那怎么样才能实现组件的封装呢?
我们可以把组件提取出来,并重写 AppRegistry 的 registerComponent 方法来实现组件的封装:
let rootViewInstance: RootView | undefined = undefined;
class RootView extends Component {
public constructor(props: {}) {
super(props);
rootViewInstance = this;
}public readonly state = {
content: null,
};
public static setContent = (view: JSX.Element) => {
rootViewInstance!.setState({ content: view });
};
public static clearContent = () => {
rootViewInstance!.setState({ content: null });
};
public render() {
const { content } = this.state;
return content && (
{content}
);
}
}const registerComponentOld = AppRegistry.registerComponent;
AppRegistry.registerComponent = (appKey, component) => {
const createRootApp = () => {
const OriginAppComponent = component();
// 获取原来的App根组件return () => (
);
};
return registerComponentOld(appKey, createRootApp);
};
export default RootView;
const styles = StyleSheet.create({
container: {
position: 'relative',
flex: 1,
},
rootView: {
position: 'absolute',
left: 0, right: 0, top: 0, bottom: 0,
zIndex: 999,
flex: 1,
},
});
至此,一个简易的 RootView 组件就装好啦,如需 Modal、Toast 功能则可以基于此组件封装,比如一个 LoadingModal 组件:
import RootView from '@/components/RootView';
const LoadingModal = {
show() {
RootView.setContent(
加载中……
);
},
hide() {
RootView.hide();
},
};
大功告成,可以愉快的玩耍啦 ~
推荐阅读
- 对抗抑郁最好的方法
- 怎样用黑谜速冻膜去黑头,|怎样用黑谜速冻膜去黑头, 最有效的去黑头的方法看这!
- 移动端h5调试方法
- 唱歌教学(导致嗓音损坏的几个常见的错误唱歌方法!)
- 拆书方法训练营
- 数组常用方法一
- 这份史上最经典的3大学习方法,清华北大学霸都在用!
- 迅捷流程图制作软件的使用方法!
- VueX--VUE核心插件
- 15个从现实焦虑中恢复精神的方法!