对于如何封装原生iOS组件供react-native,react-native中文网已经给出了方法,但是初看之下确实有很多疑惑,在自己查看了底层,并封转了UIButton供rn调用之后,也有了一些小小的看法和心得,当然自己的写法对于新手的话是很简单明了的,大神是可以直接
在iOS原生代码中
在CLFButton.h中
#import <UIKit/UIKit.h>
#import <React/RCTComponent.h>
@interface CLFButton : UIButton
@property (nonatomic, copy) RCTBubblingEventBlock onChange;
@end
在CLFButton.m中
#import "CLFButton.h"
@implementation CLFButton
@end
在CLFButtonManager.h中
#import <React/RCTViewManager.h>
@interface CLFButtonManager : RCTViewManager
@end
在CLFButtonManager.m中
#import "CLFButtonManager.h"
#import "RCTBridge.h"
#import "CLFButton.h"
@implementation CLFButtonManager
RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
RCT_CUSTOM_VIEW_PROPERTY(normalTitle, NSString, UIButton){
[view setTitle:json forState: UIControlStateNormal];
}
RCT_CUSTOM_VIEW_PROPERTY(selectedTitle, NSString, UIButton){
[view setTitle:json forState: UIControlStateSelected];
}
- (UIView *)view
{
CLFButton *btn = [CLFButton buttonWithType: UIButtonTypeCustom];
[btn addTarget:self action:@selector(btnSelected:) forControlEvents:UIControlEventTouchUpInside];
return btn;
}
- (void)btnSelected: (CLFButton *)sender{
sender.selected = !sender.selected;
if (!sender.onChange){
return;
}
sender.onChange(@{@"msg": @"我是测试信息", @"isSelected": @(sender.isSelected)});
}
@end
此处要重点说明的是RCT_CUSTOM_VIEW_PROPERTY(name, type, viewClass)这个方法,点进去之后,显示的是
/**
* This macro can be used when you need to provide custom logic for setting
* view properties. The macro should be followed by a method body, which can
* refer to "json", "view" and "defaultView" to implement the required logic.
*/
#define RCT_CUSTOM_VIEW_PROPERTY(name, type, viewClass) \
RCT_REMAP_VIEW_PROPERTY(name, __custom__, type) \
- (void)set_##name:(id)json forView:(viewClass *)view withDefaultView:(viewClass *)defaultView
我们传入的是 数据,数据类型,viewClass,但是调用的时候,数据对应的参数名称是:json, 至于view则指的是当前创建的这个view,也就是 -(UIView *)view 中所返回的这个view,至于最后的defaultView,官方给出的定义:最后,还有一个defaultView
对象,这样当JS给我们发送null的时候,可以把视图的这个属性重置回默认值。
在rn代码中
在CLFButton.js中,对控件进行了封装
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { requireNativeComponent } from 'react-native'; var CLFBtn = requireNativeComponent('CLFButton', CLFButton); export default class CLFButton extends Component { static propTypes = { normalTitle: PropTypes.string, selectedTitle: PropTypes.string, onChange: PropTypes.func, }; _onChange = (event: Event) => {
console.log(`${event.nativeEvent["msg"]},当前按钮:${event.nativeEvent["isSelected"] ? "选中状态" : "正常状态"}`, );
}
render() {
return
<CLFBtn {...
this.
props}
onChange
={
this.
_onChange}
/>
;
}}
最后是调用:
import React, { Component } from 'react'; import Dimensions from 'Dimensions' import CLFButton from "./CLFButton" export default class App extends Component<Props> { render() { return ( <CLFButton style={styles.datePickerView} normalTitle={"正常模式"} selectedTitle={"按下模式"}></CLFButton> ); } }
const styles = StyleSheet.create({ datePickerView: { backgroundColor: "#000", top: 100, width: Dimensions.get('window').width, height: 400 }, });
下面看下效果图: