RN开发初尝试

最近学习了下跨平台开发,了解了下React NativeFlutter,前者是由Facebook提供,使用JavaScript语言开发,后者由Google提供,使用dart语言开发。这两个框架都可以实现跨平台的开发,并且都比单纯使用H5页面性能好。由于RN支持热更新,并且JS语法更大众化,个人更偏向使用RN开发。

接下来我们看下如何集成RN框架到现有项目中,以及RN的一些基本概念:

RN中的组件分为两种,一种是函数式组件,一种是类组件。起初函数式组件是没有state概念的,后来添加了Hooks API,使得我们可以添加state到函数式组件中。

以下是函数式组件的代码示例:

import React from 'react';

import { Text, View } from 'react-native';

const HelloWorldApp = () => {

  return (

    <View style={{

        flex: 1,

        justifyContent: 'center',

        alignItems: 'center'

      }}>

      <Text>Hello, world!</Text>

    </View>

  );

}

export default HelloWorldApp;

类组件代码:

import React, { Component } from 'react';

import { Text, View } from 'react-native';

class HelloWorldApp extends Component {

  render() {

    return (

      <View style={{

          flex: 1,

          justifyContent: "center",

          alignItems: "center"

        }}>

        <Text>Hello, world!</Text>

      </View>

    );

  }

}

export default HelloWorldApp;

RN中组件的概念可以理解为iOS中的视图,他的原理是我们使用JS写的组件会被RN框架转成相应的iOS视图。由于React Native 组件就是对原生视图的封装,因此使用 React Native 编写的应用外观、感觉和性能与其他任何原生应用一样。我们也可以构建自己的原生组件或者到社区中查找别人已开发好的组件。


React Native是在React之上运行的,React是web端的开源UI框架。接下来介绍React的几个核心概念:

component组件

这个在上文中已经提到,用来表示视图

JSX

JSX语法使得我们可以在JS中直接输出元素:<Text>Hello world!</Text>,我们可以通过这份文档来深刻了解JSX语法,实际上,它是React.createElement(component, props, ...children) 函数的语法糖。我们也可以在元素中使用变量,例如<Text>Hello {name}!</Text>,name为提前声明的一个变量。

props

props是"properties"的简写,我们可以使用这个特性来定制组件。例如给每只<Cat>不同的name:

import React from 'react';

import { Text, View } from 'react-native';

const Cat = (props) => {

  return (

    <View>

      <Text>Hello, I am {props.name}!</Text>

    </View>

  );

}

const Cafe = () => {

  return (

    <View>

      <Cat name="Maru" />

      <Cat name="Jellylorum" />

      <Cat name="Spot" />

    </View>

  );

}

export default Cafe;

或者给一个Image组件传递source属性:

<Image

        source={{uri: "https://reactnative.dev/docs/assets/p_cat1.png"}}

        style={{width: 200, height: 200}}

   />

在JSX中引用JS值时需要使用{}括起来

state

state是组件的私人数据,不能暴露给外部组件使用。它用于记录那些随时间或者用户交互而变化的数据。

import React, { useState } from "react";

import { Button, Text, View } from "react-native";

const Cat = (props) => {

  const [isHungry, setIsHungry] = useState(true);

  return (

    <View>

      <Text>

        I am {props.name}, and I am {isHungry ? "hungry" : "full"}!

      </Text>

      <Button

        onPress={() => {

          setIsHungry(false);

        }}

        disabled={!isHungry}

        title={isHungry ? "Pour me some milk, please!" : "Thank you!"}

      />

    </View>

  );

}

const Cafe = () => {

  return (

    <>

      <Cat name="Munkustrap" />

      <Cat name="Spot" />

    </>

  );

}

export default Cafe;

开发环境搭建

搭建RN环境需要的依赖有:Node、Watchman、Xcode 和 CocoaPods

JS代码的开发推荐使用VS Code这个编辑器

Node&Watchman的安装推荐使用Homebrew命令安装

brew install node

brew install watchman

Xcode&cocoapods 如果你是iOS开发者,这两个你应该很熟悉了。


当开发环境搭建好后,我们尝试将框架集成到现有原生应用中。

1、配置项目目录结构

首先创建一个空目录用于存放 React Native 项目,然后在其中创建一个/ios子目录,把你现有的 iOS 项目拷贝到/ios子目录中。

2、安装 JavaScript 依赖包

在项目根目录下创建一个名为package.json的空文本文件,然后填入以下内容:

{

  "name": "MyReactNativeApp",

  "version": "0.0.1",

  "private": true,

  "scripts": {

    "start": "yarn react-native start"

  }

}

接下来我们使用 yarn 或 npm(两者都是 node 的包管理器)来安装 React 和 React Native 模块。请打开一个终端/命令提示行,进入到项目目录中(即包含有 package.json 文件的目录),然后运行下列命令来安装:

$ yarn add react-native

$ yarn add react@version_printed_above

所有 JavaScript 依赖模块都会被安装到项目根目录下的node_modules/目录中(这个目录我们原则上不复制、不移动、不修改、不上传,随用随装)。

把node_modules/目录记录到.gitignore文件中(即不上传到版本控制系统,只保留在本地)。

把React Native添加到你的应用中

首先配置pod文件

require_relative '../node_modules/react-native/scripts/react_native_pods'

require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '10.0'

target 'SwiftTest' do

  # Comment the next line if you don't want to use dynamic frameworks

  config = use_native_modules!

  use_react_native!(:path => config["reactNativePath"])

  # Pods for SwiftTest

  target 'SwiftTestTests' do

    inherit! :search_paths

    # Pods for testing

  end

  use_flipper!

  post_install do |installer|

    flipper_post_install(installer)

  end

  target 'SwiftTestUITests' do

    # Pods for testing

  end

end

可以用npx react-native init 项目名命令创建一个纯 RN 项目,然后去参考其 ios 目录中的 Podfile 文件

代码集成

1、创建一个index.js文件

index.js是 React Native 应用在 iOS 上的入口文件。而且它是不可或缺的!

2、添加React Native代码

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);

3、在原生项目中添加代码,使用RCTRootView将JS组建导入

首先导入React库, import React

@IBAction func highScoreButtonTapped(sender : UIButton) {

  NSLog("Hello")

  let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")

  let mockData:NSDictionary = ["scores":

      [

          ["name":"Alex", "value":"42"],

          ["name":"Joel", "value":"10"]

      ]

  ]

  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)

}


当项目写好后,我们需要启动开发服务器(即 Metro,它负责实时监测 js 文件的变动并实时打包,输出给客户端运行),进入项目根目录,运行:

$ npm start

最后在Xcode中运行项目,就可以开始进行测试了。


参考链接:https://reactnative.dev/docs/getting-started

Demo: https://github.com/JianBinWu/ReactNativePractice

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,322评论 5 465
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,288评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,227评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,015评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,936评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,534评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,995评论 3 389
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,616评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,907评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,923评论 2 315
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,741评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,525评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,016评论 3 301
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,141评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,453评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,054评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,249评论 2 339