最近學習了下跨平臺開發,了解了下React Native和Flutter,前者是由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