• 一、了解index.ios.js大家都清楚,React-Native就是在开发效率和用户体验间做的一种权衡。React-native是使用JS开发开发效率高、发布能力强,不仅拥有hybrid的开发效率,同时拥有native app相媲美的用户体验。目前...

    一、了解index.ios.js

    大家都清楚,React-Native就是在开发效率和用户体验间做的一种权衡。React-native是使用JS开发,开发效率高、发布能力强,不仅拥有hybrid的开发效率,同时拥有native app相媲美的用户体验。目前天猫也在这块开始试水。
    用编辑器打开index.ios.js文件,分析代码结构:
    1、第一句:var React = require('react-native');有Node.js开发经验的同学都清楚,require可以引入其他模块。如果没有node.js开发经验的同学,可以脑补下java的import和c++的#include。
    2、第二句代码,批量定义组件:
    var {
        AppRegistry,
        StyleSheet,
        Text,
        View,
    } = React;
    其实,这只是一个语法糖而已,比如AppRegistry我们可以这样定义:var AppRegistry = React.AppRegistry;
    3、构建Heollo World入口类。React提供了React.createClass的方法创建一个类。里面的render方法就是渲染视图用的。return返回的是视图的模板代码。其实这是JSX的模板语法,可以提前学习下。
    4、相对于web开发,我们需要提供视图的样式,那么StyleSheet.create就是干这件事的,只是用JS的自面量表达了css样式。
    5、如何引入css样式?其实在render方法返回的视图模板里已经体现出来了,即style={styles.container}.其中style是视图的一个属性,styles是我们定义的样式表,container是样式表中的一个样式。
    6、注册应用入口,这个一定不能少,否则模拟器会提示报错:
        AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
    

    二、其实你还需要看点这方面的知识

    对于React-Native开发,仅仅有基础前端开发的知识是不够的,你还需要了解和掌握的有:
    

    * Node.js基础
    * JSX语法基础
    * Flexbox布局

    三、目前需要关注的文件

    1、目前阶段有几个文件时需要注意下的:
    (1)在xcode项目代码中AppDelegate.m会标识入口文件,例如:
    jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];
    如果是网上下载别人的源码,注意此处的ip和端口是否有被修改。
    (2)闪屏界面在哪修改?在xcode项目中找到LaunchScreen.xib文件,点击,你会看到界面,这个就是启动界面,你手动添加组件或者修改文本即可,最好了解下xcode的使用。
    (3)文本编辑器打开index.ios.js文件,是js代码的入口文件,所有的代码编写从这开始,可以定义自己的模块和引入第三方模块。
    

    四、修改文件index.ios.js

    1、修改启动界面,如下图
    

    这里写图片描述

    2、添加图片和修改样式.我们在第一篇的demo基础上修改。去掉第二个和第三个<Text>,增加我们需要的图片,因为图片更具表达力,就像最近的图片社交应用很火一样。
    (1)添加Image组件,将代码修改成如下即可:
    var {
        StyleSheet,
        Text,
        View,
        Image,
    } = React;
    (2)将render返回中的模版增加Image组件视图,具体如下:
    render: function() {
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    React-Native入门学习
                </Text>
                <Image style={styles.pic} source={{uri: 'https://avatars3.githubusercontent.com/u/6133685?v=3&s=460'}}>
                </Image>
            </View>
        );
    }
    其中,Image标签的source的第一个大括号是模板,第二个大括号是js对象,js对象里面有个key是uri,表示图片的地址。
    (3)修改图片视图的样式,删除多余的样式,增加pic样式:
    var styles = StyleSheet.create({
        container: {
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center',
            backgroundColor: '#F5FCFF',
        },
        welcome: {
            fontSize: 20,
            textAlign: 'center',
            margin: 10,
            color: 'red',
        },
        pic: {
            width:100,
            height:100,
        }
    });
    (4)可以cmd + Q 停止模拟器,然后再cmd + R开启模拟器,你会发现启动界面和首页都你想要的样子:
    

    这里写图片描述

    如果终端被关闭了怎么办

     不用担心,其实只要你切到项目的根目录,命令行输入npm start即可,这样即可开发终端监听。实际上也是node.js的监听服务开启而已。如下图表示成功。
    

    这里写图片描述

    展开全文
  • 在做RN开发的时候通常离不了JS 和Native之间的通信,比如:初始化RN时Native向JS传递数据,JS调用Native的相册选择图片,JS调用Native的模块进行一些复杂的计算,Native将一些数据(GPS信息,陀螺仪,传感器等)主动...

    期待已久的新课上线啦!解锁React Native开发新姿势,一网打尽React Native最新与最热技术,点我Get!!!

    在做RN开发的时候通常离不了JS 和Native之间的通信,比如:初始化RN时Native向JS传递数据,JS调用Native的相册选择图片,JS调用Native的模块进行一些复杂的计算,Native将一些数据(GPS信息,陀螺仪,传感器等)主动传递给JS等。

    在这篇文章中我将向大家介绍在RN中JS和Native之间通信的几种方式以及其原理和使用技巧;

    接下来我将分场景来介绍JS 和Native之间的通信。

    几种通信场景:

    • 初始化RN时Native向JS传递数据;
    • Native发送数据给JS;
    • JS发送数据给Native;
    • JS发送数据给Native,然后Native回传数据给JS;

    React-Native-JS-Native-Communication

    1. 初始化RN时Native向JS传递数据

    init-data-to-js

    在RN的API中提供了Native在初始化JS页面时传递数据给JS的方式,这种传递数据的方式比下文中所讲的其他几种传递数据的方式发生的时机都早。

    因为很少有资料介绍这种方式,所以可能有很多朋友还不知道这种方式,不过不要紧,接下来我就向大家介绍如何使用这种方式来传递数据给JS。

    概念

    RN允许我们在初始化JS页面时向顶级的JS 组件传递props数据,顶级组件可以通过this.props来获取这些数据。

    iOS

    [[RCTRootView alloc] initWithBundleURL: jsCodeLocation
                                    moduleName: self.moduleName //这个"App1"名字一定要和我们在index.js中注册的名字保持一致
                             initialProperties:@{@"params":self.paramsInit}//RN初始化时传递给JS的初始化数据
                                 launchOptions: nil];
    

    接下来,我们先来看一下如何在iOS上来传递这些初始化数据。

    iOS向RN传递初始化数据initialProperties

    RN的RCTRootView提供了initWithBundleURL方法来渲染一个JS 组件,在这个方法中提供了一个用于传递给这个JS 组件的初始化数据的参数。

    方法原型:

    - (instancetype)initWithBundleURL:(NSURL *)bundleURL moduleName:(NSString *)moduleName
    		initialProperties:(NSDictionary *)initialProperties launchOptions:(NSDictionary *)launchOptions
    
    • jsCodeLocation:要渲染的RN的JS页面的路径;
    • moduleName:要加载的JS模块名;
    • initialProperties:要传递给顶级JS组件的初始化数据;
    • launchOptions:主要在AppDelegate加载JS Bundle时使用,这里传nil就行;

    通过上述方法的第三个参数就可以将一个NSDictionary类型的数据传递给顶级JS组件

    示例代码:

    [[RCTRootView alloc] initWithBundleURL: jsCodeLocation
                                    moduleName: self.moduleName
                             initialProperties:@{@"params":@"这是传递给顶级JS组件的数据"}//RN初始化时传递给JS的初始化数据
                                 launchOptions: nil];
    

    在上述代码中,我们将一个名为params的数据这是传递给顶级JS组件的数据传递给了顶级的JS 组件,然后在顶级的JS 组件中就可以通过如下方法来获取这个数据了:

     render() {
            const {params}=this.props;
            return (
                <View style={styles.container}>
                    <Text style={styles.data}>来自Native初始化数据:{params}</Text>
                </View>
                );
     }
    

    另外,如果要在非顶级页面如CommonPage中使用这个初始化数据,则可以通过如下方式将数据传递到CommonPage页面:

    export default class App extends Component<Props> {
    	...
        render() {
            return <CommonPage  {...this.props}/>;
        }
        ...
    }
    

    2. Native到JS的通信(Native发送数据给JS)

    init-data-to-js

    在RN的iOS SDK中提供了一个RCTEventEmitter接口,我们可以通过该接口实现Native到JS的通信,也就是Native将数据传递给JS。

    方法原型:

    - (void)sendEventWithName:(NSString *)name body:(id)body;
    

    所以只要我们获得RCTEventEmitter的实例就可以借助它将数据传递给JS。为了获得RCTEventEmitter的实例我们可以通过继承RCTEventEmitter <RCTBridgeModule>的方式来实现:

    DataToJSPresenter.h

    /**
     * React Native JS Native通信
     * Author: CrazyCodeBoy
     * 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
     * GitHub:https://github.com/crazycodeboy
     * Email:crazycodeboy@gmail.com
     */
    #import <React/RCTBridgeModule.h>
    #import <React/RCTEventEmitter.h>
    
    @interface DataToJSPresenter : RCTEventEmitter <RCTBridgeModule>
    
    @end
    

    DataToJSPresenter.m

    /**
     * React Native JS Native通信
     * Author: CrazyCodeBoy
     * 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
     * GitHub:https://github.com/crazycodeboy
     * Email:crazycodeboy@gmail.com
     */
    #import "DataToJSPresenter.h"
    
    @implementation DataToJSPresenter
    
    RCT_EXPORT_MODULE();
    
    - (NSArray<NSString *> *)supportedEvents
    {
        return @[@"testData"];
    }
    - (instancetype)init {
        if (self = [super init]) {//在module初始化的时候注册fireData广播
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fireData:) name:@"fireData" object:nil];
        }
        return self;
    }
    - (void)fireData:(NSNotification *)notification{//发送数据给RN
        NSString *eventName = notification.object[@"name"];
        NSDictionary *params = notification.object[@"params"];
        [self sendEventWithName:eventName body:params];
    }
    
    @end
    

    在上述方法中,我们通过RCTEventEmittersendEventWithName方法将名为eventName的数据params传递给了JS。

    提示:在DataToJSPresenter中我们实现了(NSArray<NSString *> *)supportedEvents方法,该方法用于指定能够发送给JS的事件名,所以发送给JS的eventName一定要在这个方法中进行配置否则无法发送。

    实现Native到JS的通信所需要的步骤

    接下来我们来总结一下,要实现Native到JS的通信所需要的步骤:

    • 首先要实现RCTEventEmitter <RCTBridgeModule>
    • 通过RCTEventEmittersendEventWithName方法将数据传递给JS;

    通过上述步骤,我们就可以将数据从Native发动到JS,那么如何在JS中来获取这些数据呢?

    在JS中获取Native通过RCTEventEmitter传过来的数据

    在JS中可以通过NativeEventEmitter来获取Native通过RCTEventEmitter传过来的数据,具体方法如下:

    import {NativeEventEmitter} from 'react-native';
    export default class CommonPage extends Component<Props> {
        constructor(props) {
            super(props);
            this.state = {
                data: "",
                result: null
            }
        }
    
        componentWillMount() {
            this.dataToJSPresenter = new NativeEventEmitter(NativeModules.DataToJSPresenter);
            this.dataToJSPresenter.addListener('testData', (e) => {// for iOS
                this.setState({
                    data: e.data
                })
            })
    	}
    
        componentWillUnmount() {
            if (this.dataToJSPresenter){
                this.dataToJSPresenter.removeListener('testData');
            }
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <Text style={styles.data}>收到Native的数据:{this.state.data}</Text>
                </View>
            );
        }
    }
    

    在上述代码中,我们通过NativeEventEmitteraddListener添加了一个监听器,该监听器会监听Native发过来的名为testData的数据,这个testData要和上文中所讲的eventName要保持一致:

    [self sendEventWithName:eventName body:params];
    

    https://coding.imooc.com/lesson/89.html#mid=2702
    另外,记得在JS组件卸载的时候及时移除监听器。

    以上就是在iOS中实现Native到JS通信的原理及方式,接下来我们来看一下实现JS到Native之间通信的原理及方式。

    3. JS到Native的通信(JS发送数据给Native)

    init-data-to-js

    我们所封装的NativeModule就是给JS用的,它是一个JS到Native通信的桥梁,JS可以通过它来实现向Native的通信(传递数据,打开Native页面等),接下来我就来借助NativeModule来实现JS到Native的通信。

    关于如何实现NativeModule大家可以学习参考React Native原生模的封装

    首先实现JSBridgeModule

    首先我们需要实现RCTBridgeModule

    JSBridgeModule.h

    /**
     * React Native JS Native通信
     * Author: CrazyCodeBoy
     * 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
     * GitHub:https://github.com/crazycodeboy
     * Email:crazycodeboy@gmail.com
     */
    #import <React/RCTBridgeModule.h>
    @interface JSBridgeModule : NSObject <RCTBridgeModule>
    
    @end
    

    JSBridgeModule.m

    /**
     * React Native JS Native通信
     * Author: CrazyCodeBoy
     * 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
     * GitHub:https://github.com/crazycodeboy
     * Email:crazycodeboy@gmail.com
     */
    #import "JSBridgeModule.h"
    
    @implementation JSBridgeModule
    
    RCT_EXPORT_MODULE();
    - (dispatch_queue_t)methodQueue
    {
        return dispatch_get_main_queue();//让RN在主线程回调这些方法
    }
    RCT_EXPORT_METHOD(sendMessage:(NSDictionary*)params){//接受RN发过来的消息
        [[NSNotificationCenter defaultCenter] postNotificationName:@"sendMessage" object:params];
    }
    @end
    

    代码解析

    1. JSBridgeModule中,我们实现了一个RCT_EXPORT_METHOD(sendMessage:(NSDictionary*)params)方法,该方法主要用于暴露给JS调用,来传递数据params给Native;
    2. 当收到数据后,通过NSNotificationCenter以通知的形式将数据发送出去;

    JS调用JSBridgeModule发送数据给Native

    import {NativeModules} from 'react-native';
    
    const JSBridge = NativeModules.JSBridgeModule;
    
    JSBridge.sendMessage({text: this.text})
    

    通过上述代码我就可以将一个Map类型的数据{text: this.text}传递给Native。

    4. JS发送数据给Native,然后Native回传数据给JS

    init-data-to-js

    通过上文所讲的JS到Native的通信(JS发送数据给Native),我们已经实现了JS到Native的通信,当时我们借助的是JSBridgeModule,其实它的功能还不局限于此,借助它我们还可以实现Native到JS的数据回传。

    在Native的实现

    JSBridgeModule中添加如下方法:

    RCT_EXPORT_METHOD(doAdd:(NSInteger )num1 num2:(NSInteger )num2 resolver:(RCTPromiseResolveBlock)resolve
                      rejecter:(RCTPromiseRejectBlock)reject)
    {
        NSInteger result=num1+num2;
        resolve([NSString stringWithFormat:@"%ld",(long)result]);//回调JS
    }
    

    上述代码暴露给了JS一个简单的两个整数之间的加法运算,并将运算结果回传给JS,在这里我们用的是RCTPromiseResolveBlockRCTPromiseRejectBlock两种类型的回调,分别代表成功和失败。

    在JS中的实现

    import {NativeModules} from 'react-native';
    
    const JSBridge = NativeModules.JSBridgeModule;
    JSBridge.doAdd(parseInt(this.num1), parseInt(this.num2)).then(e => {
        this.setState({
            result: e
        })
    })
    

    在JS中我们通过JSBridge.doAdd方法将两个整数num1num2传递给了Native,然后通过then来监听回传结果,整个过程采用了Promise的链式调用方式。

    参考

    展开全文
  • React Native概述什么是React NativeReact Native是Facebook在React.js Config 2015 大会上推出的一个用于开发Android和iOS App的一个框架。主要编程语言是JavaScript,UI使用JSX(一种语法类似于XML的UI描述语言)...

    React Native概述

    什么是React Native

    React Native是Facebook在React.js Config 2015 大会上推出的一个用于开发Android和iOS App的一个框架。主要编程语言是JavaScript,UI使用JSX(一种语法类似于XML的UI描述语言)。

    React Native与React.js区别

    那么React Native与React.js有什么区别呢?
    任何一种跨平台框架都有两个部分:UI和逻辑。对于这两种技术来说,UI都使用的是JSX,而逻辑都是用的是JavaScript。
    React Native与React.js的主要区别还是JSX,不管是React Native还是React.js,在UI上都是用了一种技术:虚拟DOM(Virtual DOM)。

    那么什么是虚拟DOM呢?
    其实JSX只是一种语法糖。DOM(Document Object Model 文档对象模型)是WEB前端描述网页的一种树形数据结构,WEB通过DOM管理Element,而DOM的效率是比较低的,为了提高DOM的效率,React.js提供了虚拟DOM,这项技术的工作是完全在内存中实现的,而且是增量修改DOM树,所以效率非常高。

    对于WEB来说,在实际渲染时,仍然需要DOM,所以最终渲染时,虚拟DOM仍然要转换成实际DOM。而对于Android或者iOS,就没有DOM的概念,UI完全是本地控件实现的,如Android中的TextView和EditText等。所以React Native就应运而生,如果说React.js是在运行时将虚拟DOM映射成实际DOM,那么React Native就是在运行时将虚拟DOM映射成Android或者iOS的本地控件。
    从这一点可以看出,React.js用于WEB开发,而React Native用于开发Android和iOS App,它们都将UI抽象成虚拟DOM,只是实际运行时,前者将虚拟DOM映射成了DOM,后者将虚拟DOM映射成Android或iOS的本地控件。

    为什么需要 React Native?

    What we really want is the user experience of the native mobile platforms, combined with the developer experience we have when building with React on the web.
    摘自2015.3.26 React Native的发布稿,加粗的关键字传达了React Native的设计理念:既拥有Native的用户体验、又保留React的开发效率。这个理念似乎迎合了业界普遍存在的痛点。

    React Native项目成员Tom Occhino发表的React Native: Bringing modern web techniques to mobile,详细描述了React Native的设计理念。Occhino认为尽管Native开发成本更高,但现阶段Native仍然是必须的,因为Web的用户体验仍无法超越Native:

    • Native的原生控件有更好的体验;
    • Native有更好的手势识别;
    • Native有更合适的线程模型,尽管Web Worker可以解决一部分问题,但如图像解码、文本渲染仍无法多线程渲染,这影响了Web的流畅性。

    Occhino没提到的还有Native能实现更丰富细腻的动画效果,归根结底是现阶段Native具有更好的人机交互体验。笔者认为这些例子是有说服力的,也是React Native出现的直接原因。

    “Learn once, write anywhere”同样出自Occhino的文章。因为不同Native平台上的用户体验是不同的,React Native不强求一份原生代码支持多个平台,所以不提“Write once, run anywhere”(Java),提出了“Learn once, write anywhere”。

    这里写图片描述

    这张图是笔者根据理解画的一张示意图,自下而上依次是:

    1. React:不同平台上编写基于React的代码,“Learn once, write anywhere”。
    2. Virtual DOM:相对Browser环境下的DOM而言,Virtual DOM是DOM在内存中的一种轻量级表达方式(原话是lightweight representation of the document),可以通过不同的渲染引擎生成不同平台下的UI,JS和Native之间通过Bridge通信。
    3. Web/iOS/Android:上层与用户交互的UI界面。

    React Native的优势

    上面讲到React Native的设计理念:既拥有Native的用户体验、又保留React的开发效率,是如何实现的呢?

    由于React Native的UI仍然使用Android或iOS的本地控件,所以在UI渲染上已经非常接近Native App了。尽管业务逻辑代码使用JavaScript,但由于JavaScript是即时编译的,也就是第一次使用时会将JavaScript代码编译成二进制文件,所以JavaScript得运行效率比较高。因此,React Native的运行效率要比基于HTML5、CSS等技术的PhoneGap、AppCan高很多(国内外比较流行的Hybrid混合开发方式,原理是依赖Android或iOS的webview浏览器显示HTML5,是纯的WEB程序在移动端的运行),因为这些技术直接使用HTML5进行渲染,而HTML5会大量使用DOM技术,DOM在PC端的WEB应用中也不算快,在移动端就更慢了。

    React Native一旦虚拟DOM映射本地控件完成,理论上来说,使用React Native所编写的App的运行效率和我们使用本地语言(Android的Java,iOS的OC或Swift)开发的App达到一致。

    总结:
    基于React Native的App在运行效率上接近于Native App,而且还具有混合开发模式的两个优点:

    • 热更新(无需重新编译上传App即可更新,而且还不用通过App Store审核)
    • 跨平台(降低了学习成本,使用同样的技术开发Android和iOS应用)

    React Native特点

    虚拟DOM

    提到React最先想到的就是虚拟DOM。因为这个想法实现是太好了。简而言之就是,React中UI界面是一棵DOM树,对应的我们创建一个全局唯一的数据模型,每次数据模型有任何变化,都将整个数据模型应用到UI DOM树上,由React来负责去更新需要更新的界面部分。
    传统的DOM比较需要一个节点一个节点比,时间复杂度是O(N3),React 通过分层求异的策略,对 tree diff 进行算法优化,简单说,这种虚拟DOM算法是同级的进行比较,并不进行跨层级比较,所以比较一次只需要O(N)的时间,效率非常高。当然这种情况下如果你对组件进行跨层级的移动,虚拟DOM会认为是删除了一个组件而新建了一个组件,会影响效率,所以开发中一般不进行跨层次的移动组件。
    此外,React对同层级的比较中通过设置唯一 key的策略来优化了比较策略,大大的提高了效率,具体的看下这篇博客—不可思议的react diff,写得很清楚。这里就不再赘述。

    JSX定义界面

    JSX是React的核心组成部分,它使用XML标记的方式去直接声明界面,将HTML直接嵌入到JavaScript代码中。看下示例代码:

    var React = require(‘React’);
    var message =
      <div class=“hello”>
        <span>Hello World</span>
      </div>;
    React.renderComponent(message, document.body);

    很奇怪的写法。但是确很直观,开发起来也很快。不需要过多考虑模板的概念,只需要考虑如何用代码构建整个界面。

    单向数据流

    React本身只是View层,对于事件传输层FB建议使用Flux这种单向传输架构。Flux 是一种架构思想,它分为View(视图层)、Action(动作)、Dispatcher(派发器)、Store(数据层)四层。数据流的流向参考下图:
    这里写图片描述

    首先用户访问 View,并通过View 发出用户的 Action。Dispatcher 接到Action后就要求 Store 进行相应的更新。store更新后会发一个事件到View上,最后View更新页面。简单的理解可以认为它是一种全局的消息发布订阅模型。Action可以来自于用户的某个界面操作,比如点击等;也可以来自服务器端的网络返回。当数据模型发生变化时,就触发刷新整个界面。
    看下这篇文章—Flux架构入门。在RN中用的比较多的Flux框架是Redux,可以看这个链接进行学习—Redux自述

    独特的数据模型

    React的所有数据都是只读的,如果需要修改它,那么你只能产生一份包含新的修改的数据。这样做是为了让代码更加的安全和易于维护。React将用户界面看做简单的状态机器。当组件处于某个状态时,那么就输出这个状态对应的界面。在React中,只要简单的去更新某个组件的状态,React就公以最高效的方式去比较两个界面并更新DOM树。

    React-Native生命周期

    与Activity类似,RN也有自己的生命周期。先看下我在网上找的一张生命周期图,很完整:
    这里写图片描述

    下面分点讲下各种方法:

    • getDefaultProps:在组件创建之前,会先调用 getDefaultProps(),这是全局调用一次。在组件被创建前加载。
    • getInitialState(),来初始化组件的状态。
    • componentWillMount:准备开始加载组件。在整个生命周期中只被调用一次,可以在这里做一些业务初始化操作,也可以设置组件状态。
    • componentDidMount:在组件第一次绘制之后调用,这个函数调用的时候,其虚拟DOM已经构建完成,你可以在这个函数开始获取其中的元素或者子组件了。需要注意的是,RN 框架是先调用子组件的componentDidMount(),然后调用父组件的函数。从这个函数开始,就可以和 JS 其他框架交互了,例如设置计时setTimeout 或发起网络请求。这个函数之后,就进入了稳定运行状态,等待事件触发。
    • componentWillReceiveProps:如果组件收到新的props,就会调用componentWillReceiveProps(),在这个回调函数里面,你可以根据属性的变化,通过调用 this.setState()来更新你的组件状态,这里调用并不会触发额外的 render() 调用。
    • shouldComponentUpdate:当组件接收到新的属性和状态改变的话,都会触发调用shouldComponentUpdate(…),这个函数的返回值决定是否需要更新组件,如果true表示需要更新,继续走后面的更新流程。否者,则不更新,直接进入等待状态。
    • componentWillUpdate:如果组件状态或者属性改变,并且上面的 shouldComponentUpdate(…) 返回为true,就会开始准更新组件,并调用componentWillUpdate(),在这个回调中,可以做一些在更新界面之前要做的事情。需要特别注意的是,在这个函数里面,你就不能使用this.setState来修改状态。紧接着这个函数,就会调用 render() 来更新界面了
    • componentDidUpdate:调用了 render() 更新完成界面之后,会调用 componentDidUpdate()来得到通知。
    • componentWillUnmount当组件要被从界面上移除的时候,就会调用componentWillUnmount()。在这个函数中,可以做一些组件相关的清理工作,例如取消计时器、网络请求等。
    展开全文
  • 场景: 针对目前项目需求,部分功能需要动态热部署,因此...先贴下React Native中文网是官方教程:[React Native嵌入到现有原生应用](https://reactnative.cn/docs/0.43/integration-with-existing-apps/) ...

    一、场景描述

    针对目前项目需求,部分功能需要动态热部署,因此考虑使用React Native。下面有个Demo介绍原生iOS项目是如何与React Native集成的。先贴下React Native中文网是官方教程:React Native嵌入到现有原生应用

    对老项目来说,官方推荐使用第三方包管理器CoCoaPods来自动集成,但是考虑到目前我们项目中没有使用CoCoaPods,原因如下:

    1、CoCoaPods 克隆第三方代码简直是慢
    2、CoCoaPods会自动创建一些目录,不利于项目管理。

    综上所述,因此采用手动集成,下面介绍手动集成方法。

    二、手动集成相关步骤

    1、用Xcode创建一个原生的iOS项目

    打开Xcode -> Create a new Xcode project -> Single View Application -> Demo-ReactnativeIOS
    在这里插入图片描述
    目前,我们的已经创建好了一个iOS项目Demo-ReactnativeIOS,接下来就是集成React Native的步骤了。

    2、安装react-native

    在Demo-ReactnativeIOS项目目录建一个reactnative目录,用于存放我们的react-native相关文件,再创建一个package.json文件,用于初始化react-native。
    在这里插入图片描述

    // package.json
    {
      "name": "Demo-ReactnativeIOS",
      "version": "1.0.0",
      "private": true,
      "scripts": {
        "start": "node node_modules/react-native/local-cli/cli.js start"
      },
      "dependencies": {
        "react": "15.4.1",
        "react-native": "0.39.2"
      }
    }
    

    执行安装:

    $ cd reactnative
    $ npm install

    在这里插入图片描述
    安装成功后,reactnative目录会产生一个node_modules,里面就是react-native所有依赖的项目包。安装的过程中如果出现一些警告WARN,这个没关系,是有些第三方库没有及时更新的原因。

    3、创建index.ios.js文件

    在reactnative目录下创建 index.ios.js 文件:

    "use strict";
    
    import React from "react";
    import { AppRegistry, StyleSheet, Text, View } from "react-native";
    
    class RNHighScores extends React.Component {
      render() {
        var contents = this.props["scores"].map(score => (
          <Text key={score.name}>
            {score.name}:{score.value}
            {"\n"}
          </Text>
        ));
        return (
          <View style={styles.container}>
            <Text style={styles.highScoresTitle}>2048 High Scores!</Text>
            <Text style={styles.scores}>{contents}</Text>
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
        backgroundColor: "#FFFFFF"
      },
      highScoresTitle: {
        fontSize: 20,
        textAlign: "center",
        margin: 10
      },
      scores: {
        textAlign: "center",
        color: "#333333",
        marginBottom: 5
      }
    });
    
    // 整体js模块的名称
    AppRegistry.registerComponent("RNHighScores", () => RNHighScores);
    

    index.ios.js这个就是js的初始化入口文件。到这一步,我们已经完成react-native的准备工作,接下来就是开始集成了。

    4、原生iOS项目手动集成react-native

    • 添加react-native工程文件:由于项目没有使用Cocoapods进行第三方依赖包管理,所有我们需要手动将react-native工程包添加到我们的原生ios工程中。打开 reactnative/node_modules/react-native 目录,找到相关的项目包,将React相关的工程包手动添加到项目中:
    添加 `react-native/React/React.xcodeproj`到项目中
    添加 `react-native/Libraries/Network/RCTNetwork.xcodeproj`到项目中
    添加 `react-native/Libraries/Text/RCTText.xcodeproj`到项目中
    添加 `react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj`到项目中
    添加 `react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj`到项目中
    

    添加完成如下图:
    在这里插入图片描述
    到这一步,我们已经将React相关工程包手动添加到Demo-ReactnativeIOS工程项目中。目前我们只添加了5个React工程包,如果后续开发中还需要其他工程包,按第4步依次添加就可以。

    • 添加相关frameworks文件: 接下来要将相关的frameworks文件添加到工程中, ReactnativeIOS -> TARGETS -> ReactnativeIOS -> Build Phases -> Link Binary With Libraries 。
      在这里插入图片描述

    点击 + 号,将所有 .a 文件(除了 “***-tvOS.a” 结尾)选中并添加。
    在这里插入图片描述

    • 添加libc++.tbd文件
      在这里插入图片描述
    • 添加搜索头文件的地址 Demo-ReactnativeIOS -> TARGETS -> Demo-ReactnativeIOS -> Build Settings -> Header Search Paths ,添加一条 $(SRCROOT)/reactnative/node_modules/react-native/React ,选择 recursive

    在这里插入图片描述

    • 添加 “Swift-OC-Bridging-Header.h” 桥接文件 和 “-ObjC” :(如果项目是Swift编写的话,还要添加下面两步配置,如果是OC的话,直接跳过这一步设置)

    (1) Demo-ReactnativeIOS -> TARGETS -> Demo-ReactnativeIOS -> Build Settings -> Objective-C Bridging Header,添加一条 $(PROJECT_DIR)/Demo-ReactnativeIOS/Swift-OC-Bridging-Header.h
    在这里插入图片描述

    (2) Demo-ReactnativeIOS -> TARGETS -> Demo-ReactnativeIOS -> Build Settings -> Other Linker Flags, 添加一条 “-ObjC”
    在这里插入图片描述
    这样我们就react-native集成到现有的ios工程中。

    5、添加react-native应用

    我们在原生ios应用中添加一个视图容器,用于展示react-native实现的内容。

        @IBAction func jump_Click(_ sender: Any) {
            // 加载资源文件
            let jsCodeLocation = URL(string: "http://localhost:8081/index.ios.bundle?platform=ios")
            let mockData:NSDictionary = ["scores":
                [
                    ["name":"Alex", "value":"42"],
                    ["name":"Joel", "value":"10"]
                ]
            ]
            
            // 创建RN交互容器视图
            let rootView = RCTRootView(
                bundleURL: jsCodeLocation,
                moduleName: "RNHighScores",
                initialProperties: mockData as [NSObject : AnyObject],
                launchOptions: nil
            )
            let vc = UIViewController()
            vc.view = rootView
            self.present(vc, animated: true, completion: nil)
        }
    

    到这一步,我们所有的集成工作已经完成,接下来就是运行项目。

    6、启动RN开发服务器

    在运行我们的项目之前,我们需要先启动我们的开发服务器。进入 reactnative目录 ,然后启动。

    $ cd reactnative
    $ react-native start

    在这里插入图片描述
    当看到终端中出现React packager ready,标志着我们的服务已经开启了。

    7、更新App Transport Security

    直接运行项目会报 Could not connect to development server 错误,官网中有这段话:

    在iOS 9以上的系统中,除非明确指明,否则应用无法通过http协议连接到localhost主机。 我们建议你在Info.plist文件中将localhost列为App Transport Security的例外。 如果不这样做,在尝试通过http连接到服务器时,会遭遇这个错误 - Could not connect to development server.

    打开工程中的 Info.list 文件,添加下面配置即可:

    <key>NSAppTransportSecurity</key>  
    <dict>  
        <key>NSExceptionDomains</key>
        <dict>
            <key>localhost</key>
            <dict>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>  
    

    8、运行iOS项目

    通过Xcode点击项目或者 command + R 运行项目,顺利的话就会出现如下画面。
    在这里插入图片描述

    Demo下载地址:Demo-ReactnativeIOS

    三、总结:

    在手动集成的过程中,要注意Xcode一些相关的参数配置,以及搭建基本的 React Native 开发环境(Homebrew、Node等)、网页HTML开发。

    相关链接地址:
    React Native 中文网
    HTML 教程

    展开全文
  • 原生开发,发展到今天已经非常成熟完善,已有...因此,在使用React Native开发App的过程中,我们可能需要调用RN没有实现的原生视图组件或第三方组件。甚至,我们可以把本地模块构造成一个React Native组件,提供给别

          原生开发,发展到今天已经非常成熟完善,已有组件成千上万,极大的提高了开发效率。而React Native 在Facebook的React.js conf 2015上提出,至今一年多,组件数目肯定没得和原生的相比。
    因此,在使用React Native开发App的过程中,我们可能需要调用RN没有实现的原生视图组件或第三方组件。甚至,我们可以把本地模块构造成一个React Native组件,提供给别人使用。

    本文的demo基于SDCycleScrollView,即banner,因为想不到什么好的例子,所以就把在做的项目用到的SDCycleScrollView封装下,直接给js调用。

    SDCycleScrollView为github开源的无限循环自动图片轮播器。
    地址为:https://github.com/gsdios/SDCycleScrollView
    里面会用SDWebImage,如果项目已用到SDWebImage,则建议直接把SDCycleScrollView相关代码拉进项目就OK了。

    一、对原生视图进行进一步封装

    参考其他人对原生视图的封装,大多都会新建一个视图,继承(或者子视图包含)原生视图,里面可能含有事件的调用(这里简单demo,就没用到)。
    #import "UIView+React.h",对原生视图进行扩展(这里有个重要的属性reactTag,后面会用到,作为区分用途)。

    TestScrollView.h

    #import "SDCycleScrollView.h"
    
    #import "RCTComponent.h"
    #import "UIView+React.h"
    
    @interface TestScrollView : SDCycleScrollView
    
    @property (nonatomic, copy) RCTBubblingEventBlock onClickBanner;
    
    @end

    在封装的UIView中声明RCTBubblingEventBlock或RCTBubblingEventBlock类型的block属性,才可以被当做事件导出。(新的事件导出方式,后面会用到哦)
    注意:声明block属性名称要以on开头(不确定为什么,在不做其它配置的情况下,只有on开头能成功)

    TestScrollView.m

    #import "TestScrollView.h"
    
    @implementation TestScrollView
    
    /**
     *  挺多封装原生的第三方组件都会这么写,这里还没研究透彻,就没按着去实现
    - (instancetype)initWithBridge:(RCTBridge *)bridge {
        if ((self = [super initWithFrame:CGRectZero])) {
            _eventDispatcher = bridge.eventDispatcher;
            _bridge = bridge;
            ......
        }
        return self;
    }
     */
    @end

    二、创建RCTViewManager子类来创建和管理原生视图

    原生视图都需要被一个RCTViewManager的子类来创建和管理。
    这些管理器在功能上有些类似“视图控制器”,但它们本质上都是单例 - React Native只会为每个管理器创建一个实例。
    它们创建原生的视图并提供给RCTUIManager,RCTUIManager则会反过来委托它们在需要的时候去设置和更新视图的属性。RCTViewManager还会代理视图的所有委托,并给JavaScript发回对应的事件。

    提供原生视图步骤如下:

    • 首先创建一个子类 —— 命名规范为“视图名称+Manager”. 视图名称可以加上自己的前缀,这里最好避免使用RCT前缀,除非你想给官方pull request
    • 添加RCT_EXPORT_MODULE()标记宏 —— 让模块接口暴露给JavaScript
    • 实现-(UIView *)view方法 —— 创建并返回组件视图
    • 封装属性及传递事件

    下面先贴出完整的代码,然后会对属性和事件进行进一步的解说。

    TestScrollViewManager.h

    #import "RCTViewManager.h"
    
    @interface TestScrollViewManager : RCTViewManager
    
    @end

    TestScrollViewManager.m

    #import "TestScrollViewManager.h"
    #import "TestScrollView.h"      //第三方组件的头文件
    
    #import "RCTBridge.h"           //进行通信的头文件
    #import "RCTEventDispatcher.h"  //事件派发,不导入会引起Xcode警告
    
    @interface TestScrollViewManager() <SDCycleScrollViewDelegate>
    
    @end
    
    @implementation TestScrollViewManager
    
    //  标记宏(必要)
    RCT_EXPORT_MODULE()
    
    //  事件的导出,onClickBanner对应view中扩展的属性
    RCT_EXPORT_VIEW_PROPERTY(onClickBanner, RCTBubblingEventBlock)
    
    //  通过宏RCT_EXPORT_VIEW_PROPERTY完成属性的映射和导出
    RCT_EXPORT_VIEW_PROPERTY(autoScrollTimeInterval, CGFloat);
    
    RCT_EXPORT_VIEW_PROPERTY(imageURLStringsGroup, NSArray);
    
    RCT_EXPORT_VIEW_PROPERTY(autoScroll, BOOL);
    
    - (UIView *)view
    {
        //  实际组件的具体大小位置由js控制
        TestScrollView *testScrollView = [TestScrollView cycleScrollViewWithFrame:CGRectZero delegate:self placeholderImage:nil];
        //  初始化时将delegate指向了self
        testScrollView.pageControlStyle = SDCycleScrollViewPageContolStyleClassic;
        testScrollView.pageControlAliment = SDCycleScrollViewPageContolAlimentCenter;
        return testScrollView;
    }
    
    /**
     *  当事件导出用到 sendInputEventWithName 的方式时,会用到
    - (NSArray *) customDirectEventTypes {
        return @[@"onClickBanner"];
    }
     */
    
    #pragma mark SDCycleScrollViewDelegate
    /**
     *  banner点击
     */
    - (void)cycleScrollView:(TestScrollView *)cycleScrollView didSelectItemAtIndex:(NSInteger)index
    {
    //    这也是导出事件的方式,不过好像是旧方法了,会有警告
    //    [self.bridge.eventDispatcher sendInputEventWithName:@"onClickBanner"
    //                                                   body:@{@"target": cycleScrollView.reactTag,
    //                                                          @"value": [NSNumber numberWithInteger:index+1]
    //                                                        }];
    
        if (!cycleScrollView.onClickBanner) {
            return;
        }
    
        NSLog(@"oc did click %li", [cycleScrollView.reactTag integerValue]);
    
        //  导出事件
        cycleScrollView.onClickBanner(@{@"target": cycleScrollView.reactTag,
                                        @"value": [NSNumber numberWithInteger:index+1]});
    }
    
    // 导出枚举常量,给js定义样式用
    - (NSDictionary *)constantsToExport
    {
        return @{
                 @"SDCycleScrollViewPageContolAliment": @{
                         @"right": @(SDCycleScrollViewPageContolAlimentRight),
                         @"center": @(SDCycleScrollViewPageContolAlimentCenter)
                         }
                 };
    }
    
    //  因为这个类继承RCTViewManager,实现RCTBridgeModule,因此可以使用原生模块所有特性
    //  这个方法暂时没用到
    RCT_EXPORT_METHOD(testResetTime:(RCTResponseSenderBlock)callback) {
        callback(@[@(234)]);
    }
    
    @end

    属性

    RCT_EXPORT_VIEW_PROPERTY(autoScrollTimeInterval, CGFloat);

    通过宏RCT_EXPORT_VIEW_PROPERTY完成属性的映射和导出。
    CGFloat为autoScrollTimeInterval的OC数据类型,转化成js则对应number。

    React Native用RCTConvert来在JavaScript和原生代码之间完成类型转换。
    支持的默认转换类型(部分)如下:

    • string (NSString)
    • number (NSInteger, float, double, CGFloat, NSNumber)
    • boolean (BOOL, NSNumber)
    • array (NSArray) 包含本列表中任意类型
    • map (NSDictionary) 包含string类型的键和本列表中任意类型的值

    如果转换无法完成,会产生一个“红屏”的报错提示,这样你就能立即知道代码中出现了问题。如果一切进展顺利,上面这个宏就已经包含了导出属性的全部实现。

    ps:更复杂的类型转换,则涉及到MKCoordinateRegion类型,本文没做应用,具体可参考官方文档例子。

    事件

    js和原生之间需要有事件的交互,例如,在原生实现的代理或者点击事件,js也需要实时获取到此类事件时,就需要利用事件进行交互。
    事件的实现方式有以下两种:

    1. 通过sendInputEventWithName实现
      1) 实现customDirectEventTypes,返回自定义的事件名数组(on开头才有效)

      - (NSArray *) customDirectEventTypes {
       return @[@"onClickBanner"];
      }

      2) sendInputEventWithName实现事件调用(reactTag用于实例的区分)

      [self.bridge.eventDispatcher sendInputEventWithName:@"onClickBanner"
                                                     body:@{@"target": cycleScrollView.reactTag,
                                                            @"value": [NSNumber numberWithInteger:index+1]
                                                           }];
    2. 通过RCTBubblingEventBlock实现
      1) 在封装的View中添加RCTBubblingEventBlock的block属性(on开头才有效)

      @property (nonatomic, copy) RCTBubblingEventBlock onClickBanner;

      2) 在Manager类中通过宏RCT_EXPORT_VIEW_PROPERTY完成Block属性的映射和导出

      RCT_EXPORT_VIEW_PROPERTY(onClickBanner, RCTBubblingEventBlock)

      3) 实现事件调用(reactTag用于实例的区分)

      cycleScrollView.onClickBanner(@{@"target": cycleScrollView.reactTag,
                                       @"value": [NSNumber numberWithInteger:index+1]});

    通过上面两种方式封装好的事件,在js中可以直接利用同名函数调用即可(后面会展示)。
    不过关于事件这块,挺多都没完全弄懂,希望有大神引导引导,比如为什么只能定义on开头、如何自定义、如何事件数据源的回调等等。。。

    样式

    因为我们所有的视图都是UIView的子类,大部分的样式属性应该直接就可以生效。有些属性定义,需要用到枚举,则可以利用通过原生传递来的常数方式来实现,具体实现如下:

    // 导出枚举常量,给js定义样式用
    - (NSDictionary *)constantsToExport
    {
        return @{
                 @"SDCycleScrollViewPageContolAliment": @{
                         @"right": @(SDCycleScrollViewPageContolAlimentRight),
                         @"center": @(SDCycleScrollViewPageContolAlimentCenter)
                         }
                 };
    }

    在js中调用则如下:

    //  首先获取到常量
    var TestScrollViewConsts = require('react-native').UIManager.TestScrollView.Constants;
    
    //  调用
    <TestScrollView style={styles.container} 
        pageControlAliment = {TestScrollViewConsts.SDCycleScrollViewPageContolAliment.right}
     />

    ps: 一部分组件会希望使用自己定义的默认样式,例如UIDatePicker希望自己的大小是固定的。比如大小用原生默认大小,这个例子具体可以参考官方文档的样式模块。

    三、在JS中进行调用

    在js中调用,可以有两种方式,一为直接作为扩展React组件调用,二为新建一个组件封装好,再进行调用。
    下文用第二种方式,官方推荐,逻辑比较清晰。

    1.先倒入原生组件,新建TestScrollView.js文件,在里面对TestScrollView导入,进行属性类型声明等。具体代码和解释如下:

    TestScrollView.js

    // TestScrollView.js
    
    import React, { Component, PropTypes } from 'react';
    import { requireNativeComponent } from 'react-native';
    
    // requireNativeComponent 自动把这个组件提供给 "RCTScrollView"
    var RCTScrollView = requireNativeComponent('TestScrollView', TestScrollView);
    
    export default class TestScrollView extends Component {
    
      render() {
        return <RCTScrollView {...this.props} />;
      }
    
    }
    
    TestScrollView.propTypes = {
        /**
        * 属性类型,其实不写也可以,js会自动转换类型
        */
        autoScrollTimeInterval: PropTypes.number,
        imageURLStringsGroup: PropTypes.array,
        autoScroll: PropTypes.bool,
    
        onClickBanner: PropTypes.func
    };
    
    module.exports = TestScrollView;

    2.在index.ios.js中进行调用

    index.ios.js

    var TestScrollView = require('./TestScrollView');
    
    // requireNativeComponent 自动把这个组件提供给 "TestScrollView"
    // 如果不新建TestScrollView.js对原生组件封装声明,则直接用这句导入即可
    // var TestScrollView = requireNativeComponent('TestScrollView', null);
    
    // 导入常量
    var TestScrollViewConsts = require('react-native').UIManager.TestScrollView.Constants;
    
    var bannerImgs = [
      'http://upload-images.jianshu.io/upload_images/2321678-ba5bf97ec3462662.png?imageMogr2/auto-orient/strip%7CimageView2/2',
      'http://upload-images.jianshu.io/upload_images/1487291-2aec9e634117c24b.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/480/q/100',
      'http://f.hiphotos.baidu.com/zhidao/pic/item/e7cd7b899e510fb37a4f2df3db33c895d1430c7b.jpg'
    ];
    
    class NativeUIModule extends Component {
    
      constructor(props){
        super(props);
        this.state={
            bannerNum:0
        }
      }
    
      render() {
    
        return (
          <ScrollView style = {{marginTop:64}}>
          <View>
            <TestScrollView style={styles.container} 
              autoScrollTimeInterval = {2}
              imageURLStringsGroup = {bannerImgs}
              pageControlAliment = {TestScrollViewConsts.SDCycleScrollViewPageContolAliment.right}
              onClickBanner={(e) => {
                console.log('test' + e.nativeEvent.value);
                this.setState({bannerNum:e.nativeEvent.value});
              }}
            />
            <Text style={{fontSize: 15, margin: 10, textAlign:'center'}}>
              点击banner -> {this.state.bannerNum}
            </Text>
          </View>
          </ScrollView>
        );
      }
    }
    
    //  实际组件的具体大小位置由js控制
    const styles = StyleSheet.create({
      container:{
        padding:30,
        borderColor:'#e7e7e7',
        marginTop:10,
        height:200,
      },
    });
    
    AppRegistry.registerComponent('NativeTest2', () => NativeUIModule);

    若使用第一种方式,即使用下面语句进行组件的引用:

    var TestScrollView = requireNativeComponent('TestScrollView', null);

    则会存在的这样的问题:
    虽然很方便简单,但这样并不能很好的说明这个组件的用法——用户要想知道我们的组件有哪些属性可以用,以及可以取什么样的值,他不得不一路翻到Objective-C的代码。要解决这个问题,我们可以创建一个封装组件,并且通过PropTypes来说明这个组件的接口。

    注意:我们现在把requireNativeComponent的第二个参数从null变成了用于封装的组件TestScrollView。这使得React Native的底层框架可以检查原生属性和包装类的属性是否一致,来减少出现问题的可能。

    关于属性、事件的调用,则是如下直接调用:

    <TestScrollView style={styles.container} 
              autoScrollTimeInterval = {2}
              imageURLStringsGroup = {bannerImgs}
              pageControlAliment = {TestScrollViewConsts.SDCycleScrollViewPageContolAliment.right}
              onClickBanner={(e) => {
                console.log('test' + e.nativeEvent.value);
                this.setState({bannerNum:e.nativeEvent.value});
              }}
    />

    关于事件,需要注意的是,事件事件默认传递的是字典数据类型,即json,在js中调用需要利用e.nativeEvent才能将字典取出,在具体调用里面的值。(这里也还未研究透彻、需要指导)

    React Native 与原生代码之间混合互相调用。经典项目如下:

    链接: https://pan.baidu.com/s/1kVwRnYB 密码: vuwz

    展开全文
  • React Native 充分利用了 Facebook 的现有轮子,是一个很优秀的集成作品,使用 RN 即可做到无需编译就能远程热更新 App,再加上友好的开发方式、快到爆炸的开发效率、RN 已经完爆了其他的 App 开发方式,即使是一个...
  • 本文将讲述下在原生和React Native之间的通信方式。方式和逻辑综合了自己的思维方式,主要参考了React Native中文官方文档,因为感觉它讲的方式有些不妥,所以就按自己思路组织了下文。 虽然发觉一遍文章要把所有...
  • 文章目录1. Hybrid App1.1 优势1.2 技术原理1.3 现有方案2. React Native的底层框架2.1 总体框架2.2 UI渲染2.3 通信机制2.4 小结3. 小程序的底层框架3.1 双线程...本文是学习React Native与小程序官方开发指南的笔...
  • 原文链接:... http://www.codeceo.com/article/facebook-react-native-app.html#0-qzone-1-31371-d020d2d2a4e8d1a374a433f596ad1440 非常棒的一篇经验文章,作者总结了自己学习React Native的历程,对其
  • Native、Web App、Hybrid、React Native(后面以RN简称)、Weex 间的异同点,后期同步小程序 和 PWA。 App常用开发模式简介 此处App为应用,application,并非我们通常讲的手机App。 常用的几种APP开发模式-脑图...
  • ReactNative是由Facebook公司发布的可以进行混合开发的开源技术框架。通过ReactNative可以为iOS和Android两个系统开发应用程序,“Learn once,write anywhere”。使用ReactNative开发,既拥有Native的良好人机交互...
  • 一、React Native背景 有没有朋友想过一个问题,为什么取名React Native?React是什么,Native又是什么? React React 是由Facebook推出的一个JavaScript框架,主要用于前段开发React 采用组件化方式...
  • ReactNative 集成原生项目,打包ipa和apk过程记录分析。   过程总览 将开发JS部分打成离线Bundle供原生调用 iOS 更改入口路径(安卓则配置即可) 具体见下面iOS和安卓分别打包详细过程。   ...
  • React Native预研报告

    2016-08-16 09:36:50
    React Native预研报告技术概述发展历程2014年在faceBook开发者大会上开源了react Native,这种技术是众多hybrib APP开发中的一种框架,强调了write one time,run anywhere的混合开发的另外一种可能性,受到了很多前端...
  • 在搭建配置了RN的开发环境,然后,本文记录在现有iOS项目集成React Native的过程,官方推荐使用... 新增React Native文件路径和json说明文件,进入项目根目录(*.xcodeproj文件所在目录): mkdir reactnative ...
  • React Native 简介

    2016-12-30 08:54:58
    React Native 是 Facebook 在 React.js Conf 2015 大会上推出的一个用于开发 Android 和IOS APP的一个框架。主要编语言是JavaScript,UI使用JSX(一种语法类似于XML的UI描述语言)。 那么 React Native 和...
  • 一句话概要Native、Web App、Hybrid、React Native(后面以RN简称)、Weex 间的异同点,后期同步小程序和PWA。App常用开发模式简介此处...
  • react-native技术的优劣

    2018-02-27 23:35:18
    从2017年初开始到现在,使用React-Native做项目已经一年了。我们做的是一款IM软件,嵌入在一个手机游戏平台的工程内部。之所以要采用react-native(后文简称RN)框架重构它,是因为现在游戏大厅上的所有游戏都是热...
  • React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。...衍生的 React Native 项目,目标更是宏伟,希望用写 W
  • 看了这篇技术路线对比的文章,个人倾向选择iOnic,以应对企业APP应用的开发。 第一、实话,公司养不起那么多的ios... 第三、人们最不愿意选择的是处于中间的解决方法,要么最好的,要么换方案,所以没有react native
1 2 3 4 5 ... 20
收藏数 450
精华内容 180
关键字:

oc混合开发 reactnative