美文网首页iOS Developerreact-native开发程序员
一步一步教你如何封装使用React Native原生组件

一步一步教你如何封装使用React Native原生组件

作者: 正凯 | 来源:发表于2016-09-21 11:24 被阅读7247次
    react native.jpg

    对于目前的移动端原生开发来说,想要完成一个app的开发工作是比较容易的,因为原生代码在网上所提供出来的各种开源的第三方组件已经成千上万了,足以支撑起你的业务需求。但是如果我们想要在React Native上使用第三方组件怎么办?

    众所周知,React Native自身框架也提供了一部分基础组件,已经可以基本满足我们的开发需求,但是,当我们需要使用第三方接口的时候该如何?目前市面上基本所有的第三方组件接口都还不提供对React Native的支持,所以,需要使用第三方的时候,还得我们自己来封装处理。

    接下来,我们一步一步来封装友盟分享的组件。


    1、首先导入友盟分享SDK,然后添加相关的底层依赖文件:

    1.png

    底层依赖库的添加:项目 --> build phases --> link binary with libraries
    在link binary with libraries中点加号,添加上图中的依赖文件,如下图所示。

    2.png

    2、 添加好依赖文件之后,我们接下来完成在原生中的那部分代码。
    (1) 在AppDelegate中的application:didFinishLaunchingWithOptions: 方法中设置友盟AppKey:

     // 设置友盟AppKey
    [UMSocialData setAppKey:@"57355f3e67e58ed0a50030a1"];
    

    (2) 写一个分享按钮类,继承于UIButton,然后在其中引入友盟分享头文件UMSocial.h,接下来就可以写按钮触发的分享事件了。

    #import "MyShareBt.h"
    #import "UMSocial.h"
    
    @implementation MyShareBt
    //分享按钮初始化
    - (instancetype) initWithFrame:(CGRect)frame{
      if ((self = [super initWithFrame:frame])) {
        [self addTarget:self action:@selector(share)
       forControlEvents:UIControlEventTouchUpInside];
      }
      return self;
    }
    
    // 按钮分享事件
    - (void)share {
      [UMSocialSnsService presentSnsIconSheetView:[UIApplication sharedApplication].keyWindow.rootViewController appKey:@”yourAppKey” shareText:@”test” shareImage:[UIImage imageNamed:@”yourImageName”] shareToSnsNames:[NSArray arrayWithObjects:UMShareToWechatSession,UMShareToWechatTimeline,UMShareToQzone,UMShareToSina,UMShareToTencent,nil]  delegate:nil];
    }
    
    @end
    

    (3)穿件分享组件Manager类,该类继承于RCTViewManager。创建好之后,添加标记宏RCT_EXPORT_MODULE()将该模块导出作为一个组件。最后实现-(UIView *)view方法。代码如下:

    #import "shareButtonManager.h"
    #import "RCTViewManager.h"
    #import "UMSocial.h"
    #import "MyShareBt.h"
    
    @interface shareBt : RCTViewManager
    
    @property (nonatomic) MyShareBt *bt;
    
    @end
    
    @implementation shareBt
    
    RCT_EXPORT_MODULE()
    
    - (UIView *)view
    {
      _bt = [[MyShareBt alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
      return _bt;
    }
    
    @end
    
    

    至此,原生部分代码最基本的展示部分完成了,接下来就需要在JS中进行进一步封装,以提供给JS调用。

    3、接下来实现JS中的组件封装与简单调用。
    首先导入原生组件,从导入中取得我们所创建的组件,将其作为默认的组件导出,以供其他JS调用。这里,我们其实可以直接在其他JS中调用了,但是为了进行参数的封装,我们也需要将其封装成一个单独的组件。

    import React, { Component, PropTypes } from 'react';
    import { requireNativeComponent} from 'react-native';
    
    var ShareBt = requireNativeComponent('shareBt', ZKShareBt);
    
    export default class ZKShareBt extends Component {
      render() {
        return (
          <ShareBt {...this.props} />
        );
      }
    }
    
    

    封装组件的调用。下图所示是前面封装组件的调用,这里我们已经封装了很多JS需要传递给原生的参数,接下来,我们就来说说参数以及事件处理的封装。

    <ZKShareBt style={styles.map}
                appKey={'57355f3e67e58ed0a50030a1'}
                shareText={'这是分享内容'}
                imageName={'logo'}
                //myTitle = {this.state.btText}//设置分享按钮标题
                //color={this.state.color}//设置分享按钮标题字体颜色
                btImageName = {'share_icon'} //设置分享按钮图片
       />
    

    4、参数的封装
    (1) 定义需要传递的参数

    #import <UIKit/UIKit.h>
    
    @interface MyShareBt : UIButton
    
    @property (nonatomic, copy) NSString * appKey;//友盟appkey
    @property (nonatomic, copy) NSString * shareText;//分享的文本
    @property (nonatomic, copy) NSString * imageName;//分享的图片
    @property (nonatomic, copy) NSString * myTitle;//分享按钮标题
    @property (nonatomic) UIColor * color;//按钮标题字体颜色
    @property (nonatomic, copy) NSString * btImageName;//分享按钮图片
    
    @end
    

    (2)以上参数是我们需要从JS传递给原生的,所以我们首先在原生代码中定义好所需要的参数。定义好之后,我们需要使用RCT_EXPORT_VIEW_PROPERTY宏将其导出给JS。

    #import "shareButtonManager.h"
    #import "RCTViewManager.h"
    #import "UMSocial.h"
    #import "MyShareBt.h"
    
    @interface shareBt : RCTViewManager
    
    @property (nonatomic) MyShareBt *bt;
    
    @end
    
    @implementation shareBt
    
    RCT_EXPORT_MODULE()
    
    - (UIView *)view
    {
      _bt = [[MyShareBt alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
      return _bt;
    }
    //将所需参数导出给JS
    RCT_EXPORT_VIEW_PROPERTY(appKey, NSString)
    RCT_EXPORT_VIEW_PROPERTY(shareText, NSString)
    RCT_EXPORT_VIEW_PROPERTY(imageName, NSString)
    RCT_EXPORT_VIEW_PROPERTY(myTitle, NSString)
    RCT_EXPORT_VIEW_PROPERTY(color, UIColor)
    RCT_EXPORT_VIEW_PROPERTY(btImageName, NSString)
    
    @end
    
    

    (3)重写参数set方法,并给按钮属性赋值,设置UI。

    #import "MyShareBt.h"
    #import "UMSocial.h"
    
    @implementation MyShareBt
    
    - (instancetype) initWithFrame:(CGRect)frame{
      if ((self = [super initWithFrame:frame])) {
        [self addTarget:self action:@selector(share)
       forControlEvents:UIControlEventTouchUpInside];
      }
      return self;
    }
    //重写所传递参数的set方法,并将传递过来的参数用于设置UI
    - (void)setMyTitle:(NSString *)myTitle{
      [self setTitle:myTitle forState:UIControlStateNormal];
    }
    
    - (void)setColor:(UIColor *)color{
      [self setTitleColor:color forState:UIControlStateNormal];
    }
    
    - (void)setBtImageName:(NSString *)btImageName{
      [self setBackgroundImage:[UIImage imageNamed:btImageName] forState:UIControlStateNormal];
    }
    
    - (void)share {
      [UMSocialSnsService presentSnsIconSheetView:[UIApplication sharedApplication].keyWindow.rootViewController appKey:_appKey shareText:_shareText shareImage:[UIImage imageNamed:_imageName] shareToSnsNames:[NSArray arrayWithObjects:UMShareToWechatSession,UMShareToWechatTimeline,UMShareToQzone,UMShareToSina,UMShareToTencent,nil]  delegate:nil];
    }
    
    @end
    
    

    (4)在JS中将参数封装起来。

    import React, { Component, PropTypes } from 'react';
    import { requireNativeComponent} from 'react-native';
    
    var ShareBt = requireNativeComponent('shareBt', ZKShareBt);
    
    export default class ZKShareBt extends Component {
      static propTypes = {
        /**
        *
        * 定义组件需要传到原生端的属性
        * 使用React.PropTypes来进行校验
        */
        //使用第三方分享时设置的appKey
        appKey:PropTypes.string,
    
        //要分享的内容
        shareText:PropTypes.string,
    
        //需要分享的图片名字(需要事先放在xcode工程中,只需要名字,不需要路径)
        imageName:PropTypes.string,
    
        //分享按钮标题
        myTitle:PropTypes.string,
    
        //分享按钮标题颜色
        color:PropTypes.string,
    
        //分享按钮图片
        btImageName:PropTypes.string,
      };
      render() {
        return (
          <ShareBt {...this.props} />
        );
      }
    }
    
    

    封装好之后,就可以直接调用了。

    <ZKShareBt style={styles.map}
                appKey={'57355f3e67e58ed0a50030a1'}
                shareText={'分享内容'}
                imageName={'logo'}
                //myTitle = {this.state.btText}//设置分享按钮标题
                //color={this.state.color}//设置分享按钮标题字体颜色
                btImageName = {'share_icon'} //设置分享按钮图片
       />
    

    运行结果:

    3.png 4.png

    (第一张图中,一不小心封装了其他App中的视图,这里可以通过fetch请求网络数据,获取流量之后传给原生并根据值的变化动态显示流量所占百分比。请自动忽略。。。。。。)

    以上是涉及到UI以及相关参数传递的封装工作,接下来,需要做的是事件的封装。这里事件封装用到的是RCTBubblingEventBlock宏。
    封装事件是,首先,我们需要首先在原生中先定义好需要在JS调用的方法模块。
    和之前参数定义一样,放在原生UI模块.h文件中

    MyShareBt.h

    /** button点击事件*/
    @property (nonatomic, copy) RCTBubblingEventBlock onButtonClicked;
    

    和参数一样,接下来需要导出:

    shareButtonManager.m

    RCT_EXPORT_VIEW_PROPERTY(onButtonClicked, RCTBubblingEventBlock)
    

    导出之后,这里我就简单的定义一个分享按钮点击时触发的Delegate方法

    MyShareBt.h

    @protocol ShareButtonClickedDelegate <NSObject>
    @optional
    //代理方法
    - (void)ButtonClicked;
    @end
    
    @property (nonatomic, strong) id <ShareButtonClickedDelegate> ClickDelagate;
    

    该代理方法在按钮点击分享的时候执行:

    MyShareBt.m

    - (void)share {
      //调用代理方法
      [self.ClickDelagate ButtonClicked];
      //友盟分享
      [UMSocialSnsService presentSnsIconSheetView:[UIApplication sharedApplication].keyWindow.rootViewController appKey:_appKey shareText:_shareText shareImage:[UIImage imageNamed:_imageName] shareToSnsNames:[NSArray arrayWithObjects:UMShareToWechatSession,UMShareToWechatTimeline,UMShareToQzone,UMShareToSina,UMShareToTencent,nil]  delegate:nil];
    }
    

    接下来,是实现该代理方法(我在这里设了一个随机数,传到JS中,提供给JS使用,后面JS就可以直接使用传过去的这个随机数):

    shareButtonManager.m

    #pragma mark ShareButtonClickedDelegate
    - (void)ButtonClicked {
      NSInteger x = arc4random() % 100;
      NSLog(@"原生事件%ld",x);
    // 将onButtonClicked事件导出
      _bt.onButtonClicked(@{@"randomValue": [NSNumber numberWithInteger:x]});
    }
    

    下面我们在js文件中处理:
    同样,在参数中添加上onButtonClicked。

    ZKShareButton.js

    //按钮点击事件
    onButtonClicked:PropTypes.func,
    

    添加好之后,就可以调用了,调用如下:

    onButtonClicked={(event) => {
                console.log('React事件' + event.nativeEvent.randomValue);
    }}
    

    结果显示:

    5.png

    Demo下载地址(之前的一个示例,比较粗糙,有不当之处还请多多指正,谢谢啦):
    NativeViewTestDemo
    https://github.com/cainvan/NativeViewTestDemo

    封装的一个iOS平台轮播组件及示例:
    react-native-zkbanner
    ReactBannerDemo

    封装的一个H5端的轮播组件:react-zkcarousel

    相关文章

      网友评论

      • 我就是阿泽:封装了一个原生的iOS组件,在RN调用的时候如果想在原生组件上添加一个RN的view该如何实现呢?
      • 老马到了呀:shareButtonManager.m 这个文件不知道怎么处理, 一直没写通.
      • HJXu:挺不错的一篇讲解原生与RN页面交互的文章
      • Smallwolf_JS:有没有demo发给我下
      • 云上月:赞,我想照着楼主的思路,努力封装微信支付,,,gogo
      • 3da1492bab3f:先感谢一下楼主的辛劳工作!然后开始学习:+1:
      • Yourtion:楼主给力~之前也封装过一个模块,还要考虑iOS跟Android兼容 :joy: https://github.com/yourtion/ReactNative-SuperID
        正凯:@Yourtion :smiley: 你好厉害 :+1:
      • harvey_hui:正需要
        正凯:@harvey_hui :blush: :blush: :blush:
      • 挂着铃铛的兔:感谢楼主!
        正凯: @挂着铃铛的兔 晚上回去找找,把Demo传给你吧,现在在外面😬
        挂着铃铛的兔:@正凯 现在的问题是,照着你这个教程一步一步来,但就是各种失败。。。是不是中间缺了什么导出的过程啊? 控制台提示我没有找到shareButtonManager
        正凯:@挂着铃铛的兔 : :relaxed: :relaxed: :relaxed:
      • henry_g:谢谢,正在找继承友盟的资料,明天上班按照文章尝试下,有问题了再联系您 :smile:
        正凯: @国恒 加油!
      • RemisKrlet:有demo嘛
        正凯: @Tmycc 例子没有传,你可以看看https://github.com/cainvan/react-native-zkbanner的封装

      本文标题:一步一步教你如何封装使用React Native原生组件

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