react-native入门,编写静态页面,集成原生项目

React-Native技术调研

0.前提:

搭建环境:https://reactnative.cn/docs/getting-started/,
分mac/win/linux,平台分android/ios。

1.创建一个新项目

使用rn创建一个项目和把rn技术集成到一个现有的原生项目是有差别的。

//创建和运行一个rn项目:
react-native init AwesomeProject
cd AwesomeProject
react-native run-ios

编译和运行需要一段时间...耐心等待..根据rn版本的不同,ios虚拟机也不不同,比如最新的0.57版本的是iphoneX,低版本的rn默认创造的ios虚拟机就老一点。

注意官网中特别提到:

!!!注意!!!:init 命令默认会创建最新的版本,而目前最新的 0.45 及以上版本需要下载 boost
等几个第三方库编译。这些库在国内即便FQ也很难下载成功,导致很多人无法运行iOS项目!!!中文网在论坛中提供了这些库的国内下载链接。如果你嫌麻烦,又没有对新版本的需求,那么可以暂时创建0.44.3的版本。

我在rn版本0.57.5,react-cli版本2.0.1直接init创建项目没有遇到以上问题。

几个常用操作

  1. cmd+r 刷新,可配置热更新,调出菜单enable liveload
  2. cmd+d 调出菜单

2.试着用RN写一个静态页面

https://github.com/ZhangMingZhao1/react-native-pratice/tree/master/earphone_guide

3.集成到一个原生项目

这里以一个rn集成到ios object-c为例,现实中这种情况可能也更多一些。

a.

用xcode新建一个单页面应用,语言选择object-c,名字为ReactNativeDemo,在项目根目录下,新建ReactNative文件夹,用于存放跟reactnative相关文件。(后面简称rn)

b.

在rn文件夹中新建一个package.json,内容为:

{
  "name": "ReactNativeDemo",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "dependencies": {
    "react": "16.0.0",
    "react-native": "0.51.0"
  }
}

注意版本严格规定

c.

进入rn文件夹,npm install,在rn文件夹新建index.js,以前版本是inex.ios.js。
内容为:

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

class ScoresView 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,
    },
  });
  
// 注册组件,程序入口
// 第一个参数:注册模块名称,这里亲测不和项目名一致也可以,但是好多资料说名字要和项目名一致
// 第二个参数:函数,此函数返回组件类名,程序启动就会自动去加载这个组件
AppRegistry.registerComponent('App', () => ScoresView);

d.

进入项目根目录,安装cocoapods,

brew install cocoapods

我的mac下会报个错,在一个文件下没有权限写入,而homebrew现在禁止使用sudo执行,根据提示的指令可以收回那个文件的权限,复制粘贴执行就好。

安装好后,在根目录使用pod init,在生成的Podfile中内容改为:

source 'https://github.com/CocoaPods/Specs.git'
react_native_path = './ReactNative/node_modules/react-native'
platform :ios, ‘9.0’
use_frameworks!

target 'ReactNativeDemo' do
# 'node_modules'目录一般位于根目录中
# 但是如果你的结构不同,那你就要根据实际路径修改下面的`:path`
pod 'React', :path => react_native_path, :subspecs => [
'Core',
#'BatchedBridge', # 0.45 版本以后需要添加
'CxxBridge',
'DevSupport', # 如果RN版本 >= 0.43,则需要加入此行才能开启开发者菜单
'RCTText',
'RCTImage',
'RCTNetwork',
'RCTWebSocket', # 这个模块是用于调试功能的
# 在这里继续添加你所需要的模块
]
# 如果你的RN版本 >= 0.42.0,则加入下面这行
pod 'yoga', :path => react_native_path + '/ReactCommon/yoga'
# Third party deps
pod 'DoubleConversion', :podspec => react_native_path + '/third-party-podspecs/DoubleConversion.podspec'
pod 'GLog', :podspec => react_native_path + '/third-party-podspecs/GLog.podspec'
pod 'Folly', :podspec => react_native_path + '/third-party-podspecs/Folly.podspec'

end

这个文件类似npm的package.json,记录了所需文件的依赖,所以下一步就是

pod install

e.

在总ios项目中修改http的安全策略,在info.plist加上:

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

f.

用xcode打开项目,在Main.storyboard拖入一个按钮,在ViewController.m中加入头文件:

#import <React/RCTRootView.h>

再增加一个按钮的跳转方法:

- (IBAction)pushToReactNativeView:(id)sender {
    NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
    
    RCTRootView *rootView =
    [[RCTRootView alloc] initWithBundleURL: jsCodeLocation
                                moduleName: @"App"
                         initialProperties:
     @{
       @"scores" : @[
               @{
                   @"name" : @"Alex",
                   @"value": @"42"
                   },
               @{
                   @"name" : @"Joel",
                   @"value": @"10"
                   }
               ]
       }
                             launchOptions: nil];
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view = rootView;
    [self presentViewController:vc animated:YES completion:nil];
}

可能会出现加载出错,这是因为pod install安装的文件没有加载进来,重启xcode项目,重新打开项目即可。
然后把ViewController.m文件中的#import <fishhook/fishhook.h> 改为 #import "fishhook.h",不然后面运行可能会报错。

g.

给这个按钮和这个方法绑定起来,进入keyboard,按住 ctrl,点击按钮会出现一个箭头,指向左上角的ViewContrller,可出现一个框,选择刚才写的pushToReactNativeView方法,会在右下角看到关联了。
这部可详见iOS学习之基础控件添加和事件绑定,推荐一个链接:https://www.jianshu.com/p/6eb302a62956

h.

进入到rn文件夹,npm start 启动node服务器,这时会进入dev状态,动态打包。回到xcode,运行项目,点击按钮,就会看到跳转到rn写的页面。

4.RN打包给原生项目使用

a.

在rn项目根目录中创建release_ios 文件夹,(打包必须创建文件夹)具体可以自己命名,作为资源目标的输出文件目录。
在根目录下执行打包命令:

react-native bundle --entry-file index.js --platform ios --dev false --bundle-output release_ios/main.jsbundle --assets-dest release_ios/

会看到release_ios下多出assets文件夹(如果有图片),和两个jsbindle文件.

b.

将main.jsbundle和assets拖入Xcode的项目导航面板中,选择默认导入即可(位置和里面的文件夹同级)
在这里插入图片描述

修改上面的ViewController,m,
在这里插入图片描述

将端口动态引入改为本地,让React Native去使用我们刚才导入的jsbundle,这样以来我们就摆脱了对本地nodejs服务器的依赖。当然也可以将jsbundle 放到自己的远程服务器中,更换远程的服务器文件就可以加载jsbundle,为了提高性能我们可以在本地做一次缓存。@后面是自己打包文件的名字不加后缀。

c.

ios app的打包就可以看官网了:https://developer.apple.com/support/app-store-connect/

5.留下的疑问,待继续研究

  1. npm start后打包的文件是在哪里放着的,找了一下没找到,难道和webpack dev一样使用了memory-fs-js,把临时打包文件动态写进了内存里吗?
  2. 大家可以补充..etc
posted @ 2018-11-23 18:36  Lawliet__zmz  阅读(987)  评论(0编辑  收藏  举报