美文网首页
RN 组定义组件

RN 组定义组件

作者: 口子窖 | 来源:发表于2018-09-05 17:36 被阅读116次

RN 组定义组件

背景

自定义RN native Component,js绑定事件与native通信

CheckBox

遵循微信小程序的规范,实现组件,首先我们来看一下微信小程序的规范

checkboxGroup

多项选择器,内部由多个checkbox组成。

属性名 类型 默认值 说明
onbindchange EventHandle <checkbox-group/>中选中项发生改变是触发 change 事件,detail = {value:[选中的checkbox的value的数组]}

checkbox

多选项目。

属性名 类型 默认值 说明
value String <checkbox/>标识,选中时触发<checkbox-group/>的 change 事件,并携带 <checkbox/> 的 value
disabled Boolean false 是否禁用
checked Boolean false 当前是否选中,可用来设置默认选中
color Color checkbox的颜色,同css的color

微信小程序语法兼容

由于RN框架的自身特性,说明两点:

1、小程序中的组件命名为"-",而我们使用的RN框架并不支持这种命名方式,大概率还是由于我没有吃透RN的用法,总之目前为止没有方案可以支持"-"命名,所以统一改成了驼峰。

2、change事件,RN中必须要加"on"前缀,所以,更改了规范,EventHandle的属性名都加了前缀

NSString *RCTNormalizeInputEventName(NSString *eventName)
{
  if ([eventName hasPrefix:@"on"]) {
    eventName = [eventName stringByReplacingCharactersInRange:(NSRange){0, 2} withString:@"top"];
  } else if (![eventName hasPrefix:@"top"]) {
    eventName = [[@"top" stringByAppendingString:[eventName substringToIndex:1].uppercaseString]
                 stringByAppendingString:[eventName substringFromIndex:1]];
  }
  return eventName;
}

上方代码片段是截取RN框架中的RCTEventDispatcher.m,片段描述了处理eventName的"诡异"操作,估计是为了代码规范特定加的。

开展组件代码

目标

我们的成果是这样的,很常规的一个CheckBox

checkbox.png

怎么使用

<SCheckboxGroup onbindchange={this.onclick}>
<SLabel>
  <SText selectable={false}>国家选择</SText></SLabel>
<SLabel>
  <SCheckbox value='中国' />
  <SText selectable={false}>中国</SText></SLabel>
<SLabel>
  <SCheckbox value='新加坡' />
  <SText selectable={false}>新加坡</SText></SLabel>
<SLabel>
  <SCheckbox value='马来西亚' />
  <SText selectable={false}>马来西亚</SText></SLabel>
</SCheckboxGroup>

组件组织结构

一个RN原生组件,包含两部分,native代码和js桥接代码,native代码实现了具体的view、各种事件,js桥接代码实现了对native组件的封装,属性以及事件的包装,最终能被js业务代码所使用

组件代码究竟怎么写

因为CheckBox有组的概念,所以checkbox实际包含了checkboxGroup和checkbox两个组件

从业务逻辑上区分,checkboxGroup负责处理事件,checkbox负责视图和事件的触发

CheckboxGroup

SMPCheckboxGroup.h

#import <UIKit/UIKit.h>
#import <React/RCTComponent.h>
@interface SMPCheckboxGroup : UIView
@property (nonatomic, copy) RCTBubblingEventBlock onbindchange;
- (void)addValue:(NSString *)value;
- (void)removeValue:(NSString *)value;
@end

这边定义了两个方法addValue和removeValue,group里面添加和删除元素

onbindchange是当勾选时候触发的事件,会传递到js业务层。

SMPCheckboxGroup.m

#import "SMPCheckboxGroup.h"
@interface SMPCheckboxGroup()
@property (nonatomic,strong) NSMutableArray *values;
@end
@implementation SMPCheckboxGroup
- (SMPCheckboxGroup *)init{
    if (self = [super init]) {
        self.values = [NSMutableArray arrayWithCapacity:1];
    }
    return self;
}
- (void)didMoveToSuperview{
    [self drawCheckBox];
}
- (void)drawCheckBox{
    self.backgroundColor = [UIColor clearColor];
}
- (void)addValue:(NSString *)value{
    [self.values addObject:value];
    [self sendBoxValueToJs];
}
- (void)removeValue:(NSString *)value{
    [self.values removeObject:value];
    [self sendBoxValueToJs];
}
- (void)sendBoxValueToJs{
    if (_onbindchange) {
        self.onbindchange(@{@"detail":@{@"value":self.values}});
    }
}
- (void)drawRect:(CGRect)rect{
    [super drawRect:rect];
}
@end

属性values用来存储勾选的值,是一个数组

不管对元素的添加和删除都要触发sendBoxValueToJs ,向js发消息。发消息的原理其实就是通过block

SMPCheckboxGroupManager.h

#import <React/RCTViewManager.h>
@interface SMPCheckboxGroupManager : RCTViewManager
@end

1、命名是有规范的,必须要xxxManager结尾,在写js桥接程序的时候会提到为什么非得这么写

SMPCheckboxGroupManager.m

#import "SMPCheckboxGroup.h"
#import "SMPCheckboxGroupManager.h"
@implementation SMPCheckboxGroupManager
RCT_EXPORT_MODULE()
RCT_EXPORT_VIEW_PROPERTY(onbindchange, RCTBubblingEventBlock)
#pragma mark init
- (UIView *)view{
    SMPCheckboxGroup *view = [[SMPCheckboxGroup alloc] init];
    return view;
}
@end

1、RCT_EXPORT_MODULE() 导出module的预处理,必须要写

2、RCT_EXPORT_VIEW_PROPERTY ,导出事件和属性,js才能使用。第一个参数是属性名,第二个是类型

js桥接

import PropTypes from "prop-types";
import React from "react";
import { requireNativeComponent } from "react-native";
class SCheckboxGroup extends React.Component {
  _onbindchange = (event) => {
    if (!this.props.onbindchange) {
      return;
    }
    this.props.onbindchange(event.nativeEvent);
  }
  render() {
    return <SMPSCheckboxGroup {...this.props} onbindchange={this._onbindchange}
    />;
  }
}
SCheckboxGroup.propTypes = {
  onbindchange: PropTypes.func,
};
var SMPSCheckboxGroup = requireNativeComponent("SMPCheckboxGroup", SCheckboxGroup);
export default SCheckboxGroup;

1、propTypes属性列表

2、requireNativeComponent方法中,"SMPCheckboxGroup"名称是取自SMPCheckboxGroupManager,规定将Manager去掉的字符串传入第一个参数。

checkbox

原理都与checkboxGroup相似,但如果是radio的话,就稍微复杂一点。radio是选择唯一性,需要排他。

1、捕捉到radio的点击

2、查到当前radio所属的radiogroup

3、遍历radiogrou下面所有的radio

3、排他,将出了当前值意外的都更改为未选中状态

查到同一radiogroup下面的所有radio

- (UIView *)getFatherSRadioGroup:(UIView *)view
{
    if (view==nil) {
        return nil;
    }
    if ([view.superview isKindOfClass:NSClassFromString(@"SMPRadioGroup")]) {
        return view.superview;
    }else{
    return [self getFatherSRadioGroup:view.superview];
    }
}

遍历radiogroup下面所有的radio

//遍历父视图的所有子视图,包括嵌套的子视图
-(void)TraverseAllSubviews:(UIView *)view array:(NSMutableArray *) array{
    for (UIView *subView in view.subviews) {
        if (subView.subviews.count) {
            if ([subView isKindOfClass:NSClassFromString(@"SMPRadio")]) {
                [array addObject:subView];
            }else{
                [self TraverseAllSubviews:subView array:array];
            }
        }
        NSLog(@"%@",subView);
    }
}

排他,将出了当前值意外的都更改为未选中状态

- (void)changeOtherBrothers:(NSArray *)array
{
    for (UIView *v in array) {
        if ([v isKindOfClass:NSClassFromString(@"SMPRadio")] && v != self) {
            SMPRadio *radio = (SMPRadio *)v;
            radio.RadioChecedColor.backgroundColor = [UIColor whiteColor];
            radio.selectedRadio = NO;
        }
    }
}

相关文章

  • RN 组定义组件

    RN 组定义组件 背景 自定义RN native Component,js绑定事件与native通信 CheckB...

  • RN系列:Android中远程调试RN及混淆打包

    【简述RN集成到Android原生项目】【RN系列:RN使用Android原生控件或自定义组件】【React Na...

  • r n 坑

    rn 引用原生控件的时候,自定义组件的首字母必须大写。。。不然会出现错误。 2.rn 进行block。 rn调用...

  • ReactNative 遇见的坑

    基于0.39,Android平台 1、ListView 吃内存,无法回收内存; 用Native 来自定义RN组件 ...

  • React native 实战 --布局篇(mac)

    RN的布局 RN的布局是组件化的方式进行组合布局,没有定义flex情况下的话,布局很随意 样式的坑 要注意盒子之间...

  • render方法中如何使用if else 判断

    学RN的同学知道,在组件的render方法中我们可以通过JSX来定义组件的具体布局和显示( JSX 用于在 Jav...

  • ReactNative--自定义下拉刷新组件(iOS)

    RN有提供原生的下拉刷新组件(菊花刷新),但并没有提供自定义刷新组件的方法。也许你会照着RCTRefreshCon...

  • RN的ScrollView和ListView

    1、ScrollView组件 RN封装了Android与IOS两大操作系统提供的滚动视图组件,该组件支持RN组件V...

  • React Native学习笔记之组件生命周期

    React Native学习笔记之组件生命周期 单一组件生命周期 首先看一下RN组件生命周期简略说明图 组件初始化...

  • 非单文件组件

    Vue中使用组件的三大步骤 一、定义组件(创建组件) 二、注册组件 三、使用组...

网友评论

      本文标题:RN 组定义组件

      本文链接:https://www.haomeiwen.com/subject/zoxzwftx.html