2018-03-28 17:24:06 qq_30211165 阅读数 1091

rn嵌入第三方分享.目前各大第三方平台还不支持rn集成(登入,支付,分享)所以我们必须要用迂回战术这一部分我们用原生集成然后rn传值调用原生.
代码
准备阶段
原生接入第三方分享这一部分略是个体力活
无非就是添加权限,添加白名单,申请key和导入sdk等
假设你原生第三方分享已经集成完毕了那么接下来我们就用rn传值过来并且调用

#import "FirstViewController.h"
//rn于ios传值用
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTBridgeModule.h>
//极光分享
#import "JSHAREService.h"
//极光分享自定义组件
#import "ShareView.h"
#import "AppDelegate.h"
@interface FirstViewController ()<RCTBridgeModule>

@property (nonatomic, strong) ShareView *shareView;

@property(nonatomic,copy) NSString *ShareImageUrl;
@end

@implementation FirstViewController

- (void)viewDidLoad {
    [super viewDidLoad];
  self.title = @"RN第三方分享";

  [self initRN];

}
-(void)initRN{
  NSURL *jsCodeLocation;

  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"RNThreeApp"
                                               initialProperties:nil
                                                   launchOptions:nil];
  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.view = rootView;

}

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(doShare:(NSString*)imageUrl callback:(RCTResponseSenderBlock)callback){
  NSLog(@"rn传过来的参数为%@",imageUrl);
  self.ShareImageUrl = imageUrl;
  if (imageUrl.length>0) {
    NSLog(@"%@",imageUrl);
    dispatch_async(dispatch_get_main_queue(), ^{
      [self.shareView showWithContentType:1];
    });
    NSString *OsStr = @"分享成功了";
    callback(@[[NSNull null],OsStr]);
  }

}





//懒加载
- (ShareView *)shareView {
  if (!_shareView) {
    _shareView = [ShareView getFactoryShareViewWithCallBack:^(JSHAREPlatform platform, JSHAREMediaType type) {
      [self shareLinkWithPlatform:platform];
    }];
     AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    [app.window.rootViewController.view addSubview:self.shareView];
  }
  return _shareView;
}


- (void)shareLinkWithPlatform:(JSHAREPlatform)platform {
  JSHAREMessage *message = [JSHAREMessage message];

  NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.ShareImageUrl]];

  message.mediaType = JSHAREImage;
  message.platform = platform;
  message.image = imageData;

  [JSHAREService share:message handler:^(JSHAREState state, NSError *error) {

    NSLog(@"分享回调");

  }];
}

rn代码

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  Button,
  View
} from 'react-native';
//ios原生传值用
var NativeTest =  require('react-native').NativeModules.FirstViewController;
// const instructions = Platform.select({
//   ios: 'Press Cmd+R to reload,\n' +
//     'Cmd+D or shake for dev menu',
//   android: 'Double tap R on your keyboard to reload,\n' +
//     'Shake or press menu button for dev menu',
// });

type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        <Button onPress={this.onPressShar}
        title="分享"
        />
      </View>
    );
  }

  onPressShar(){
//点击分享将值传给原生并且原生拉起第三放分享//分享一个图片,链接,标题
核心代码
NativeTest.doShare('http://bmob-cdn-15476.b0.upaiyun.com/2018/01/19/b45a865bee3343e7a2279b056addf4c5.png',(error,events)=>{
  if(error) {
   // console.error(error);
  }else{

   // alert(events);
  }
});
  }



}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});
2016-10-17 13:29:23 ctrip_tech 阅读数 195

图片描述

随着智能手机和移动互联网最近几年的迅猛发展,在其背后的开发技术也在经历着日新月异的变化。

移动开发从最早期的原生 iOS Objective C、Android Java到基于H5 Hybrid,Android插件化/iOS动态脚本,再到现在火热的React Native, 其背后都是业务发展对技术需求的表现。

早期的纯Native开发成本高,同样业务iOS&Android各需要开发一份,迭代发布慢,都需要通过应用市场审核发布;后来,以Cordova为代表的H5 Hybrid解决了这个痛点,但是H5在性能体验方面却大打折扣;再后来,动态化插件在Android上解决了性能这一问题,但是成本依然高昂,且只能解决Android的问题。

一年半前,随着React Native的到来,这些痛点都被一一解决。目前看来,它是移动开发的一大方向,后起的Weex,微信小程序,无一例外,都有参考React Native的设计。

不过React Native框架的使用,以及和现有业务的整合,性能优化,门槛并不低,各个公司在业务实践过程中都遇到各自不同的问题。本次沙龙,我们将就RN框架优化,业务实践方面的问题来做分享。

10月23日,携程上海总部,一起来聆听移动开发最前沿的声音~

活动详情

图片描述

议题简介

  • 《React Native优化实践》-赵辛贵

图片描述

ReactNative 已成为业内 App 的热门开发技术,然而其框架自身还不够成熟。稳定性、性能,和Native相比,都还有一定的差距。为了让RN达到类似Native的体验和稳定性,以及将该技术尽可能低成本地引入到携程各个业务团队,提高开发效率,我们对RN做了大量优化。

本次分享将会围绕以下议题:
1、React Native 框架的业务落地:介绍携程的 Ctrip React Native 框架的组成和业务应用情况;
2、React Native 性能优化:介绍携程在 React Native 拆包(各业务独立打包,实现动态更新)、页面预加载(实现页面秒开)等多方面的性能优化方案。

  • 《React Native项目实战之火车票业务探索之旅》-姚瑞琼

图片描述

火车票BU作为携程体系下的重要环节,要兼顾良好的App用户体验及迅速的业务迭代,一个月左右一个App版本的节奏很难满足,而React Native跨平台、媲美原生App的用户体验以及无需发版的升级模式等优势无疑让人眼前一亮。

加上基础的Ctrip React Native框架对RN的性能优化、业务封装以及拆包发布等的大力支持,火车票现已上线3条业务线、将近20个RN页面,经历了携程App三个大版本的迭代与考验。

本次分享将着重介绍火车票在RN实践过程中踩过的坑和对应的解决方案,以及在实际开发过程中,遇到的各种问题以及优化步骤。

听众收益:
1、了解React Native在火车票产品中的应用
2、了解RN与Hybrid及Native开发之间的异同
3、了解实际产品的RN开发、发布及维护的完整周期

  • 《波罗蜜全球购的RN实践》-好大

图片描述

波罗蜜全球购是主打“只卖当地店头价”和“视频互动直播”的自营跨境电商,发展十分迅速,是近两年跨境电商中的一匹黑马。

随着业务量和业务范围的增加,采用原生的方式越来越难以满足日益增加和变化的需求。我们需要一套更加灵活的技术框架更快更好地支撑我们的业务,同时获得更好的用户体验,所以我们选择了 React Native(以下简称 “RN” )。

RN 目前处于一个快速变化的阶段(几乎两周一个大版本),而且社区还不成熟。在这个“吃螃蟹”的过程,需要解决很多实际的工程问题。

本次主要和大家分享:
1、在“波罗蜜全球购”中 RN 的使用情况
2、如何搭建一个“简单,实用,可靠”的 RN 发布系统

报名通道:活动行,戳这里http://www.huodongxing.com/event/3356637539000

说明:本次分享会更适合对React Native有一定了解,并且已经在进行实践的同学。初学者请谨慎报名。

2016-06-15 21:16:39 u014484863 阅读数 6967

React Native控件之View视图解析

(一)前言

这篇文章我们来讲解一下View控件,今天的内容是非常基础,但是是非常有用的东西。特别注意View控件的属性和方法,要记住一些非常常用的属性与方法。

(二)View介绍

View作为创建UI时候最基础最常用的组件,在react-native中View组件是支持FlexBox布局(FlexBox布局的详细使用讲解)、CSS样式以及相关触摸处理的容器组件。该组件我们可以嵌套在其他视图View里边,并且可以包含多种类型的子视图。在Web、Android、iOS三种平台上面,View视图分别对应三种平台原生视图,在iOS中对应UIView,在Web中对应< div >标签,Android对应android.view,下面举出一个简单的例子:
这里写图片描述

上诉代码创建一个高度为100的View组件,padding为20,也就是说填充物为20,再在这个视图里面嵌套一个红色的View视图。然后继续在红色视图中嵌套一个Text组件。

其实在写React Native项目的时候,一般在实际开发中,都会将样式写成CSS样式,这样写代码读起来比较清晰,而且便于以后项目维护,以下就是使用CSS方式重写上述代码:

'use strict'
import React, { Component } from 'react';
import  {
   AppRegistry,
   StyleSheet,
   Text,
   View
} from 'react-native'

var PerfectProject = React.createClass({
    render: function(){
       return (
          <View style={styles.first_view}>
            <View style={styles.second_view}>
               <Text>这是一个红色View!</Text>
            </View>
          </View>
       );
    },
});

var styles = StyleSheet.create({
  first_view:{
    flexDirection:'row',
    height:100,
    padding:20
  },
  second_view: {
    backgroundColor:'red',
    flex:1
  },
});

AppRegistry.registerComponent('PerfectProject',() => PerfectProject);

(三)View的属性方法

View属性方法介绍如下:

序号 名称 属性或者方法 类型 说明
1 accessibilityLabel 属性 string
2 accessible 属性 bool 当为true时,表示该元素是可以进行访问,默认情况下所有可触摸的元素控件都是可以访问的
3 onAccessibilityTap 方法 function 该当accessible为true的时候并且用户对控件View做了一个Tap(轻轻的触摸或者点击)的手势
4 onLayout 方法 function 当组件的布局发生变动的时候,会自动调用下面的方法:{nativeEvent: { layout: {x, y, width, height}}}。该事件当重新计算布局的时候回立即进行触发,不过界面可能不会立即刷新,特别当布局动画正在加载中的时候。
5 onMagicTap 方法 function 当accessible为true的时候,当用户双指点击(Magic Tap)的时候,进行触发。

其他的一些方法如下(下面很多是关于事件响应者链的,都比较简单的,就不着重讲解的,有兴趣大家都可以去测试一下):

  • onMoveShouldSetResponder
  • onMoveShouldSetResponderCapture
  • onPresponderGrant
  • onResponderMove
  • onResponderReject
  • onResponderRelease
  • onResponderTerminate
  • onResponderTerminationRequest
  • onStartShouldSetResponder
  • onStartShouldSetResponderCapture
  • pointerEvents enum(‘box-none’, ‘none’, ‘box-only’, ‘auto’)(触摸事件是否可以进行穿透控件View);
  • removeClippedSubviews:该控件由于进行优化性能,尤其在一些滑动控件上面。该属性生效的要求如下:首先子视图的内容非常多,已经超过父容器,并且子视图和父容器视图都有overflow:hidden风格样式。

【注意】关于上面一些方法的具体使用,后面在讲到事件响应者的时候会进行着重讲解。

(四)View样式——Style便签介绍

在React Native的Style样式布局中,有许多Style标签,简要介绍一下:

Style标签 说明
FlexBox 弹性布局(详细介绍请点击
backfaceVisibility enum(‘visible’,’hidden’)定义界面翻转的时候是否可见
borderColor 边框颜色,这边几个就是代表上下左右边框的颜色(borderTopColor,borderRightColor,borderBottomColor,borderLeftColor)
borderStyle 边框线的风格,这个和CSS样式是一样的,enum(’solid’,’dotted’,’dashed’)
opacity 设置透明度
elevation 高度,设置Z轴,可以产生立体效果
transforms 动画属性(详细介绍请点击
backgroundColor 颜色
borderRadius 边框圆角大小,其他几个是上下左右边框的圆角.borderTopLeftRadius,borderTopRightRadius,borderBottomLeftRadius,borderBottomRightRadius
borderWidth 边框宽度,另外四个是上下左右的边框宽度:borderTopWidth,borderLeftWidth,borderBottomWidth,borderRightWidth
overflow 设置超过容器内容显示与否

下面有几个特殊的属性,在这里介绍所有平台通用以及只能在Android平台上有效果的属性。

属性名 作用 平台
testID 可以根据该testID在测试的时候定位该View 全平台
accessibilityComponentType 定义是否该UI组件和原生组件一致化处理 android平台
accessibilityLiveRegion enum(‘none’,’polite’,’assertive’) 该当View发生更新时候的,是否需要通过用户,不过该只对Android4.4以及以上的平台设备有效果 android平台
collapsable 布局合并优化使用 android平台
importantForAccessibility enum(‘auto’, ‘yes’, ‘no’, ‘no-hide-descendants’) 设置视图响应事件等级 android平台
needsOffscreenAlphaCompositing 设置View是否需要渲染和半透明度效果处理的先后次序。 android平台
renderToHardwareTextureAndroid 设置是否需要GPU进行渲染 android平台

可以参考官方例子UIExplorer项目,这个项目包含所有组件的例子代码:https://github.com/facebook/react-native/blob/master/Examples/UIExplorer/ViewExample.js

2017-12-12 13:29:48 weixin_34415923 阅读数 43

本文原创首发于公众号:ReactNative开发圈,转载需注明出处。

React Native 文档查看组件:react-native-doc-viewer,可以在手机上直接打开文档,支持远程和本地文档。支持的文档格式:xls,ppt,doc,xlsx,pptx,docx,png,jpg,pdf,mp4。支持iOS和Android。

安装方法

npm install react-native-doc-viewer --save
react-native link react-native-doc-viewer

API说明

  • openDoc 打开远程货或本地文档
  • openDocb64 打开Base64字符串格式文档
  • openDocBinaryinUrl 打开二进制文件
  • playMovie 打开视频文件

clipboard.png

使用示例

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Platform,
    Button,
    Alert,
    ActivityIndicator
} from 'react-native';
import OpenFile from 'react-native-doc-viewer';
var RNFS = require('react-native-fs');
var SavePath = Platform.OS === 'ios' ? RNFS.MainBundlePath : RNFS.DocumentDirectoryPath;
export default class Component02 extends Component {

    static navigationOptions = ({ navigation }) => ({
        title: `${navigation.state.params.name}`,
    });

    state = { animating: false }
    /*
    * Handle WWW File Method
    * fileType Default == "" you can use it, to set the File Extension (pdf,doc,xls,ppt etc) when in the Url the File Extension is missing.
    */
    handlePress = () => {
        this.setState({ animating: true });
        if (Platform.OS === 'ios') {
            OpenFile.openDoc([{
                url: "https://calibre-ebook.com/downloads/demos/demo.docx",
                fileNameOptional: "test filename"
            }], (error, url) => {
                if (error) {
                    this.setState({ animating: false });
                } else {
                    this.setState({ animating: false });
                    console.log(url)
                }
            })
        } else {
            //Android
            this.setState({ animating: true });
            OpenFile.openDoc([{
                url: "https://www.huf-haus.com/fileadmin/Bilder/Header/ART_3/Header_HUF_Haus_ART_3___1_.jpg", // Local "file://" + filepath
                fileName: "sample",
                cache: false,
                fileType: "jpg"
            }], (error, url) => {
                if (error) {
                    this.setState({ animating: false });
                    console.error(error);
                } else {
                    this.setState({ animating: false });
                    console.log(url)
                }
            })
        }

    }


    /*
    * Handle Local File Method
    * fileType Default == "" you can use it, to set the File Extension (pdf,doc,xls,ppt etc) when in the Url the File Extension is missing.
    */
    handlePressLocal = () => {
        this.setState({ animating: true });
        if (Platform.OS === 'ios') {
            OpenFile.openDoc([{
                url: SavePath + "demo.docx",
                fileNameOptional: "test filename"
            }], (error, url) => {
                if (error) {
                    this.setState({ animating: false });
                } else {
                    this.setState({ animating: false });
                    console.log(url)
                }
            })
        } else {
            OpenFile.openDoc([{
                url: SavePath + "demo.jpg",
                fileName: "sample",
                cache: false,
                fileType: "jpg"
            }], (error, url) => {
                if (error) {
                    this.setState({ animating: false });
                } else {
                    this.setState({ animating: false });
                    console.log(url)
                }
            })

        }

    }

    /*
    * Binary in URL
    * Binary String in Url
    * fileType Default == "" you can use it, to set the File Extension (pdf,doc,xls,ppt etc) when in the Url you dont have an File Extensions
    */
    handlePressBinaryinUrl = () => {
        this.setState({ animating: true });
        if (Platform.OS === 'ios') {
            OpenFile.openDocBinaryinUrl([{
                url: "https://storage.googleapis.com/need-sure/example",
                fileName: "sample",
                fileType: "xml"
            }], (error, url) => {
                if (error) {
                    console.error(error);
                    this.setState({ animating: false });
                } else {
                    console.log(url)
                    this.setState({ animating: false });
                }
            })
        } else {
            OpenFile.openDocBinaryinUrl([{
                url: "https://storage.googleapis.com/need-sure/example",
                fileName: "sample",
                fileType: "xml",
                cache: true
            }], (error, url) => {
                if (error) {
                    console.error(error);
                    this.setState({ animating: false });
                } else {
                    console.log(url)
                    this.setState({ animating: false });
                }
            })
        }
    }
    /*
    * Base64String
    * put only the base64 String without data:application/octet-stream;base64
    * fileType Default == "" you can use it, to set the File Extension (pdf,doc,xls,ppt etc) when in the Url you dont have an File Extensions
    */
    handlePressb64 = () => {
        this.setState({ animating: true });
        if (Platform.OS === 'ios') {
            OpenFile.openDocb64([{
                base64: "",
                fileName: "sample.png",
                fileType: "png"
            }], (error, url) => {
                if (error) {
                    console.error(error);
                    this.setState({ animating: false });
                } else {
                    console.log(url)
                    this.setState({ animating: false });
                }
            })
        } else {
            OpenFile.openDocb64([{
                base64: "",
                fileName: "sample",
                fileType: "png",
                cache: true
            }], (error, url) => {
                if (error) {
                    console.error(error);
                    this.setState({ animating: false });
                } else {
                    console.log(url)
                    this.setState({ animating: false });
                }
            })
        }
    }

    /*
    * mp4 Video
    */
    handlePressVideo(video) {
        this.setState({ animating: true });
        if (Platform.OS === 'ios') {
            OpenFile.playMovie(video, (error, url) => {
                if (error) {
                    console.error(error);
                    this.setState({ animating: false });
                } else {
                    console.log(url)
                    this.setState({ animating: false });
                }
            })
        } else {
            this.setState({ animating: false });
            Alert.alert("Coming soon for Android")
        }
    }

    setToggleTimeout() {
        this.setTimeout(() => {
            this.setState({ animating: !this.state.animating });
            this.setToggleTimeout();
        }, 2000);
    }

    render() {
        return (

            <View style={styles.container}>
                <ActivityIndicator
                    animating={this.state.animating}
                    style={[styles.centering, { height: 80 }]}
                    size="large" />
                <Text style={styles.welcome}>
                    Doc Viewer React Native
        </Text>
                <Button
                    onPress={this.handlePress.bind(this)}
                    title="打开远程文档"
                    accessibilityLabel="See a Document"
                />
                <Button
                    onPress={this.handlePressLocal.bind(this)}
                    title="打开本地文档"
                    accessibilityLabel="See a Document"
                />
                <Button
                    onPress={this.handlePressBinaryinUrl.bind(this)}
                    title="打开远程二进制文档"
                    accessibilityLabel="See a Document"
                />
                <Button
                    onPress={this.handlePressb64.bind(this)}
                    title="打开Base64字符串"
                    accessibilityLabel="See a Document"
                />
                <Button
                    onPress={() => this.handlePressVideo("http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4")}
                    title="打开视频"
                    accessibilityLabel="See a Document"
                />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

Screenshots

clipboard.png

示例源码

GitHub - forrest23/ReactNativeComponents: React Native组件大全

组件地址

GitHub - philipphecht/react-native-doc-viewer: React Native Doc Viewer (Supports file formats: xls,ppt,doc,xlsx,pptx,docx,png,jpg,pdf)

举手之劳关注我的微信公众号:ReactNative开发圈

clipboard.png

2016-04-11 11:41:35 Jeff_NJUT 阅读数 654
先上一个ppt,不过好像要翻墙,内容跟本文基本一致,看不到可以先忽略

这里是我临时写的一个React Native的试水项目,打开后等会会看到gif动画演示。 https://github.com/xinyu198736/htmljs-ReactNative 欢迎star和watch。

三端的三观

大家别拍我,起这么个diao渣天的标题是为了吸引你进来,大家不要太在意用词。先介绍下我自己,我是一个普普通通的开发者,平常喜欢自己捣鼓 技术,所以涉猎比较广,一些不太常用只是摸过几腿的技术就不说了,至少现在每天都摸的技术大概有三端:前端,服务端,客户端。这篇文章是我作为一个“三 端”开发者角度对React Native的一点点看法,不会太具体,但是希望对大家的认识能有个不同角度的指导。

作为一个ios开发者,我的经验大概有2年左右,虽然不是专业选手,但是一个app开发需要涉及到的东西基本都接触过,坑也趟过不少,其实ios开发的体验还是不错的,熟练了以后构建app还是很快的,不过里面也有不少麻烦的地方,例如:

  • 代码量大(那长长的方法名)
  • 布局麻烦(特别是AutoLayout,光理解这个概念就要好几天,而且很难用)
  • 编译调试耗时(比android快很多,但是还是很慢)
  • OC语言和Cocoa框架有些冗余的地方(一堆堆的属性和继承过来的方法)
  • 用代码定义样式麻烦(cocoa给UIView加点阴影边框设置字体等,那代码不忍直视)
  • 有时候定位问题也挺难,动不动就报个 main thread的报错,完全下不了手(可能是我没掌握好方法)
  • pods管理代码,安装个代码等半天,有时候还要翻墙,很不稳定,跟npm之类的没法比。

而对于前端来说,还会对ios的开发有些其他的疑问,例如:

  • 要是能用css写样式就好了
  • 要是能实时调试界面样式就好了
  • 要是支持闭包就好了
  • 要是回调写起来跟JS一样方便就好了(指oc中的block)
  • 要是代码跟js一样简洁就好了

而React Native其实正是迎着这些问题而上,然后结合三端的优点,搞出来的一个移动端开发框架。

且来看下他有哪些动人之处。

美丽动人的RN

我拿起React Native的第一次,就被它彻底打动了,抛开他的语法,对于前端来说奇奇怪怪的jsx(后面会讨论),它的确解决了我作为一个三端工程师在不同技术端切 换的时候备受的一些困扰,所以那天晚上,我完全没睡着,翻来覆去的,然后跑到朋友圈发了句:“激动人心的技术,未来的发展方向”。第二天早晨,提前一两个 小时就醒过来,继续写了几句RN,那酸爽,那心情。可能作为一个纯粹的前端或者纯粹的ios开发,很难理解,但是对于一个游走在三端的工程师,我看到了一 个真正意义上的统一方案,而且,它足够简单。

React Native的上手很快,去看一下它的文档,总共就一点点:入门,组件,功能。每个页面都短短的一两页,的确就是这么简单。不过这里我并没有打算把这篇文章写成一篇入门教程,所以并不会教你如何构建一个简单的RN应用。

大概总结来,React Native让我觉得值得一提的动人之处:

1.把cocoa里面的controller和view统一成了component,其实RN里只有component这个组件概念,既可以扮演页面级别的组件(controller),也可以扮演一个模块级别的组件(UIView)。入门门槛降低了很多。

2. 动态绑定,这个React的基本功能,被带到了客户端开发中来,数据和视图是动态绑定的,数据发生变化,视图会跟着变化,很多操作视图的代码都可以省略了。

3. 引入了类似于CSS(一个子集)的样式管理,可以内嵌到模块,也可以全局使用,定义样式变得非常简单通用。

4. 引入了Flexbox布局,把ios本身复杂的AutoLayout简化,使用很方便,学习起来也更简单。

5. 引入了方便的npm管理,有大量现成的nodejs包可以用(例如moment,underscore等常用模块),还可以把自己项目模块搞到内部npm上做通用组件,另外,npm上还有不少别人写的react native的插件。例如下面这个。

6. 第三方组件里有一个可以把icon font引入项目的组件,可以在任何显示图标的地方直接用icon font显示,灰常方便。

7. 调试很方便,一次编译后,每次改了js代码,只需要在模拟器里command+R即可重新加载代码。有问题会直接报错,里面有代码行数等详细信息。

8. 完整封装了各种js内置的方法,例如:setTimeout,setInterval,XMLHttpRequest,localstorage,console.log等,都是用oc原生方法封装的。

9. 引入ES6的支持,可以使用各种新特性,例如最常用的箭头函数,解决this作用域乱套的问题。

一口气列举出这么多动人的地方,ReactNative这姑娘还真是不一般,简直校花级别。(小插曲,我觉得React性格就是个姑娘,感性而 简单,而Angularjs则像是一位硬汉,笨重但是踏实而且很全面)。不过,人无完人,现阶段ReactNative也有不少缺点,有些缺点可能会非常 制约他的发展,急需改进,不过还好RN目前只是开发阶段,并不是正式版,该有的都会有的。

并非完美无瑕

我看来,目前ReactNative至少有这么几个比较大的问题:

  • 组件不全,第三方组件也不全,遇到某些特殊功能,需要捣鼓很久,例如摄像相关的,文件读写,文件上传之类的组件。
  • 性能并非媲美原生,还是有一些损耗的,特别是交换大数据的时候,例如读取相册。
  • 只有ios版,限制了在某些公司生产环境的使用。android版不知道目前什么状态。
  • ios和android代码并非通用,有可能会需要维护两套,或者在代码内做一些判断。
  • 并非网上大家说的,写一次代码,多端通用,网页版和客户端版完全不是一个概念,只有部分代码可重用。
  • 把代码都打包到bundle里面,不知道苹果对这种开发方式是否会不太喜欢,甚至拒绝上线。
  • 实际开发的时候,还是需要了解底层原理,自己开发跟原生桥接的组件,这个对普通前端来说是一个很大的挑战。

有些问题,随着时间的推移会慢慢解决,有些问题,则很难说,例如开发方式的问题。

对前端开发和客户端开发意味着什么?

ReactNative一出来,有的人一头钻进去开始研究,大部分人却只是稍作了解,然后就投入到了论战的圈子里。例如大家对React的 jsx开发方式的批判,对React组件化开发方式的批判。其实还是那个问题:任何脱离场景的技术讨论都是耍流氓。React并非万能药水,它的出现不是 要大一统整个前端界的所有问题,它事实上只是为了解决一小类问题,所以不要指望你的产品能够用React来解决那些他并不擅长的问题。而对于 ReactNative来说,其实我觉得这正是体现React价值的一个非常吻合的一个场景。React在这个问题中扮演的角色,就是上面讲到的他解决的 那些问题,足够多,而且很完美,这就是他存在的价值,不容否认。

所以,大家要从理性的角度去看待新技术,不要一味排斥,不要套用现有的思维和场景。当你用这样的态度去看RN,你就能看到他的优点和缺点,自做抉择。

我从一个前端的角度来看ReactNative,有这样的感觉:

  • 它不是万能药水,只是一种高效的解决方案,不要期望它为你解决了所有问题,要不要使用,还是需要根据场景衡量,而不是脱离开来说它是好的或者是坏的。
  • 事实上,目前看来,客户端开发更适合写RN,因为要了解客户端的那套开发理念,对前端来说成本挺高,而对于客户端开发,成本只是理解一个语言。
  • RN跟Html5没有冲突,二者场景并不一样,它要取代的是本来客户端开发的部分工作,而不是H5页面,因为在这些场景下它并没有明显优势。
  • 对于遇到瓶颈的前端来说,它是一个很好的扩展自己技术栈的方向,有得玩,而且很好玩。

从一个客户端开发的角度来看:

  • 用ReactNative的确简化了很多OC开发中的繁琐步骤,比swift也是更胜一筹。
  • JS、React社区的活跃度很高,有很大的开源组件开发空间,是一个不错的参与开源社区的机会,大家很需要一些桥接原生的新组件。
  • NPM真的是太方便快速了!社区里无数可用的工具库,在OC的世界里可不常见。
  • RN是前端侵占客户端开发的触角么?其实很难说,它跟NodeJS一样,试图侵入另一个领域,但是深入是非常难的,大部分人浮于表面,反而帮你承接了最恼人的顶层业务部分。
  • 不过你应该会觉得js真不严谨,而且回调很蛋疼,闭包很奇怪,作用域很难理解。也许是时候抛开自己旧时代对js的理解了,现在ES6也是一门很先进的语言了。

未来的开发模式?

最近只是在试水,踩坑,然后我真的准备在公司里把这个事情推动起来,因为我觉得它的确是有意义的,对开发效率有非常明显的提升,不过现阶段还只 能是尝试,毕竟它没有发布正式版,然后还只有ios。不过踩坑也是为了积累,正式版发布后我们就可以快速切入了,到时候就会走的快人一步。

不过可以想象一下未来在生产环境的开发模式,跟NodeJS用来做中间件类似,其实RN最后应该会扮演一个承接前端业务的角色,这部分开发工作,可以是前端来做,也可是客户端来做,主要是用基础组件完成业务开发,其实就类似于中间件的形式。

而客户端开发的主要工作是构建基础组件,封装一些原生桥接的组件供RN使用,基本上是通用组件,应该是一个全公司级别的客户端架构组的概念。

前端做表层业务 + 客户端做底层组件支持。Perfect,还真是有点期待呢!

不扯蛋,埋头去学

不要总是试着去评论一个技术,而是在大家都在学习的时候赶紧迎头赶上去,学习总不会白白浪费的,你看那些大牛,虽然他们以前学习的技术一直在不断被淘汰,但是他们啥时候掉过队。

列一些资料:

看个差不多就先试着写个app出来,边做边学,乐趣无限

另外欢迎加入ReactNative QQ群:456662818

没有更多推荐了,返回首页