JS 使用原生UI组件

使用原生UIView

  • Native端:
  1. 首先创建一个RCTViewManager的子类。 @interface NativeView : RCTViewManager @end

  2. 添加RCT_EXPORT_MODULE()宏标记导出的模块名称 RCT_EXPORT_MODULE(MyNativeView)

  3. 实现-(UIView *)view方法,返回对应的native视图给JS

- (UITextField*)view {
    UITextField * field = [UITextField new];
    field.text = @"BBBB";
    field.textColor = [UIColor blueColor];
    field.textAlignment = UITextAlignmentCenter;
    return field;
}
  • JS端:
  1. 用一个js文件来导入模块。 NativeView.js
import { requireNativeComponent } from 'react-native';
// requireNativeComponent 自动把'RNTMap'解析为'RNTMapManager'
export default requireNativeComponent('MyNativeView');
  1. 然后在其他js里使用即可。
import NativeView from './MyNativeView'
<NativeView style={{width:150, height:50, backgroundColor:"green"}}>
</NativeView>

image

封装原生属性

可以将view 方法里返回的视图的属性封装并供给JS端来设置.

以上面代码为例,Native 端:

RCT_EXPORT_VIEW_PROPERTY(userInteractionEnabled, BOOL)

JS端:

<NativeView style={{width:150, height:50, backgroundColor:"green"}}
        userInteractionEnabled={false}>
        </NativeView>

那么view返回的UITextField 将无法接收点击等操作。

JS 修改原生组件属性

  1. 为原生组件声明一个属性,在设置时,Native属性函数可以获取到 JS端设置的值。
RCT_CUSTOM_VIEW_PROPERTY(frameTest, CGRect, UITextField)
{
    CGRect rect = [RCTConvert CGRect:json]; //json是js端传递的数据结构的字典化数据
    view.frame = rect; //view就是设置属性的那个视图对象
}
  1. 在JS端,直接设置 frameTest 属性即可,注意保持传递的结构体的key 与 CGRect的一致
NativeView.propTypes = {
     frameTest: PropTypes.shape({
      x: PropTypes.number,
      y: PropTypes.number,
      width: PropTypes.number,
      height: PropTypes.number,
    }),
};
<NativeView style={{width:150, height:50, backgroundColor:"green"}}
        userInteractionEnabled={true} frameTest={{x:1.1, y:2.3, width:50, height:40}}>
        </NativeView>

原生组件发送给JS的事件

在js使用Native组件时,如果native组件发生了事件(比如点击,滚动),需要将事件和数据传递给 JS端。 可以自定义事件,数据则是一个 Dictionary。

  • Native端:

    1. Native端的view 返回的视图类型,需要给它新增一个 RCTBubblingEventBlock 的property。 以上面的 UITextField 为例
    @interface MyUITextField : UITextField
    @property (nonatomic, copy) RCTBubblingEventBlock onHello;
    @end
    @implementation MyUITextField
    @end
    
    1. 然后给 NativeView 新增一个导出属性。(必须与上面那个同名)
    RCT_EXPORT_VIEW_PROPERTY(onHello, RCTBubblingEventBlock)
    
    1. 在发生事件时,调用返回视图的 onHello,并将相关数据一并给回
    - (void)tapped:(UITapGestureRecognizer*)gesture {
        dispatch_async(dispatch_get_main_queue(), ^{
            MyUITextField * field = gesture.view;
            if (field.onHello) {
              field.onHello(@{@"first":@(12)});
            }
        });
    }
    
  • JS 端:

    1. 编写 onHello的响应函数即可
    <NativeView
          style={{width:250, height:50, backgroundColor:"black"}} 
          userInteractionEnabled={true}
          onHello={ (event) => {
              console.log('event data='+event.nativeEvent.first) //PS:事件传递过来的event参数不会直接是Native的Dictionary,它的 nativeEvent 属性才是
          }}
          >
    </NativeView>
    

    大PS:事件名必须以 “on” 开头,否则js无法响应!

代码实例: NativeView.h NativeView.m NativeView.js Modal.js