将友盟分享封装为React Native组件

最近一直在考虑原生组件的封装问题,看到一片很好的文章,就分享下啦~大笑大笑
react



react native.jpg

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

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

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


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


1.png

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


2.png

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

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

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

#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调用。fetch

三、接下来实现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'} //设置分享按钮图片
   />

四、参数的封装
(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