【跨平台】ReactNative 入门初探
- 环境搭建与资料
- 基础知识
- JS/TS Html基础
- React 基础
- 异步编程处理
- Promise
- Generator
- async
- UI 组件
- 定义和使用style
- 宽度和高度
- FlexBox
- 触摸组件
- 常用交互
- Redux
- 基础概念
- 与安卓通信
- 参考
- 相关类
- 注解等
- 构建打包
- 示例
- 常用参数
- 自定义RN插件
环境搭建与资料
- RN中文网
- RN开发者网站
- 菜鸟教程 - React
- react教程
- ES6 语法
- Redux中文文档
基础知识
JS/TS Html基础
- 常用HTML标签
HTML标签 | 说明 | 示例 |
---|---|---|
<div> | 用于定义文档中的一个区域或节(division) | <div>这是一个区域</div> |
<p> | 用于定义段落 | <p>这是一个段落。</p> |
<a> | 用于创建超链接 | <a href="https://www.example.com">这是一个链接</a> |
<img> | 用于在页面中嵌入图像 | <img src="image.jpg" alt="图片"> |
<ul> | 用于创建无序列表 | <ul><li>无序列表项 1</li><li>无序列表项 2</li><li>无序列表项 3</li></ul> |
<ol> | 用于创建有序列表 | <ol><li>有序列表项 1</li><li>有序列表项 2</li><li>有序列表项 3</li></ol> |
<li> | 用于定义列表中的每一项 | <ul><li>无序列表项 1</li><li>无序列表项 2</li><li>无序列表项 3</li></ul> |
<table> | 用于创建表格 | <table><tr><td>行1,列1</td><td>行1,列2</td></tr><tr><td>行2,列1</td><td>行2,列2</td></tr></table> |
<tr> | 用于定义表格中的行 | <table><tr><td>行1,列1</td><td>行1,列2</td></tr><tr><td>行2,列1</td><td>行2,列2</td></tr></table> |
<td> | 用于定义表格中的单元格 | <table><tr><td>行1,列1</td><td>行1,列2</td></tr><tr><td>行2,列1</td><td>行2,列2</td></tr></table> |
<h1> | 用于定义最高级别的标题 | <h1>这是一个标题</h1> |
<h6> | 用于定义最低级别的标题 | <h6>这是一个标题</h6> |
- 动态特性和对象属性的灵活性
JavaScript 中的动态特性和对象属性的灵活性指的是你可以在运行时动态地添加、修改和删除对象的属性。这意味着你可以在代码执行过程中动态地设置一个变量,或者向一个对象动态地添加新的属性。
- 什么是DOM
DOM 是文档对象模型(Document Object Model)的缩写。它是一种用于表示和操作 HTML、XML 和 XHTML 文档的编程接口。在 Web 开发中,DOM 提供了一种将网页文档表示为树状结构的方式,使得开发者可以通过编程方式访问、修改和操作网页的内容、结构和样式。通过 DOM,开发者可以使用 JavaScript 或其他编程语言来动态地改变网页的外观和行为。
- function关键字
可以定义 函数和类,在ES6 后一般用class定义类。
ES6之后还可以用箭头函数去定义函数
const greet = (name) => {return "Hello, " + name + "!";
}console.log(greet("Bob")); // 输出 "Hello, Bob!"
- 函数扩展
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
function getPoint() {const x = 1;const y = 10;// 属性名就是变量名, 属性值就是变量值return {x, y};
}console.log(getPoint().x)
console.log(getPoint().y)
React 基础
- props 和 state
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据
特性 | 可变性 | 所有权 | 作用 | 备注 |
---|---|---|---|---|
state | 可变 | 组件内部拥有和设置 | 管理组件的内部状态 | 更新state:<font style="color:green;">this</font><font style="color:gray;">.</font><font style="color:rgb(0, 85, 170);">setState</font><font style="color:olive;">({</font><font style="color:rgb(0, 85, 170);">date</font><font style="color:gray;">: </font><font style="color:green;">new</font><font style="color:teal;">Date</font><font style="color:olive;">()})</font><font style="color:gray;">;</font> |
props | 不可变 | 由父组件传递 | 在组件之间传递数据 |
- ts与tsx文件
.ts 和 .tsx 文件都与 TypeScript 相关。.ts 文件是常规的 TypeScript 文件,而 .tsx 文件用于包含 JSX(JavaScript XML)语法的 TypeScript 文件。这使得 TypeScript 能够与 React 组件和其他基于 JSX 的代码一起使用。
- 事件处理
存在绑定的概念,在jsx里面使用 this
需要提前绑定
- 组件生命周期
方法 | 阶段 | 目的 |
---|---|---|
“constructor()” | 挂载 | 初始化组件状态和绑定事件处理程序。 |
“render()” | 挂载 | 渲染组件的 UI。 |
“componentDidMount()” | 挂载 | 在组件挂载到 DOM 后执行网络请求或订阅事件。 |
“shouldComponentUpdate()” | 更新 | 控制组件在接收新 props 或 state 时是否重新渲染。 |
“render()” | 更新 | 重新渲染组件的 UI。 |
“componentDidUpdate()” | 更新 | 在组件更新后执行 DOM 操作或网络请求。 |
“componentWillUnmount()” | 卸载 | 在组件卸载前清理定时器、取消订阅等操作。 |
- 组件导入和导出
- 参考
// 具名导出
export function Profile() {return (<imgsrc="https://i.imgur.com/QIrZWGIs.jpg"alt="Alan L. Hart"/>);
}
// 默认导出
export default function Gallery() {return (<section><h1>了不起的科学家们</h1><Profile /><Profile /><Profile /></section>);
}...import Gallery from './Gallery.js'; // 默认导入
import { Profile } from './Gallery.js'; // 具名导入
异步编程处理
Promise
- promise的三种状态:
pending
、fulfilled
、rejected
- 无法取消,且一旦新建会立刻执行;从pending到fulfilled/rejected 后会 状态凝固 ,状态不再改变;
- 执行完成后,再添加监听器会 立刻 得到结果
- 基础使用示例
var p = new Promise((onSuccess,onFail) => {// 这里的第二个参数onFail 也可以省略if(true){onSuccess(1)}else{onFail(1)}console.log("It will still be executed here")
})p.then(v =>{console.log("onSuccess:" + v)
},r =>{console.log("onReject:" + r)
}).catch(e =>{// 如果没有设置 then的第二个参数 -- reject的回调,则会走到catch的回调// 建议不设置第二个参数,直接设置catch的回调console.log("onError:" + e)
}).finally(()=>{// 不管执行了then 还是catch 最终都会走到console.log("finally")
})// output
// It will still be executed here
// onSuccess:1
// test.ts:17
// onFinally
- 包装多个Promise
Promise.all()
全都resolve才回调 resolve否则回调第一个被rejcet的原因Promise.race()
回调第一个子Promise的结果Promise.allSettled()
全部都执行完(reject/resolved)回调resolvedPromise.any()
全部失败才回调rejected
- 工具类方法
Promise.resolve()
将现有对象转化为PromisePromise.reject(reason)
返回一个状态为rejected的Promise
Generator
- 文档参考
- 基础用法
function* test(){console.log("output 1")yield 1 // 执行到这里 产出一个值 挂起 console.log("output 2")yield 2console.log("output 4")return 4
}var data = test()
console.log(data.next())
console.log(data.next())
console.log(data.next())// consoleoutput 1
{value: 1, done: false}
output 2
{value: 2, done: false}
output 4
{value: 4, done: true}
Generator.next()
往下执行,传入true表示重置方法,从第一个yield开始执行;传入值表示给上一个yeild的产出进行赋值(方法内可能也用到这个产出的值);Generator.return(value)
结束方法块并返回值,将返回{value: 给定的值, done: true}
Generator.throw(value)
抛出异常,优先会被内部捕获,而后内部方法执行完毕,将被外部捕获(若有)
var g = function* () {try {yield;} catch (e) {console.log('内部捕获', e);}··};var i = g();i.next();try {i.throw('第一个异常');i.throw('第二个异常');} catch (e) {console.log('外部捕获', e);}
async
- 可以理解为 Generator 的语法糖,就是把 * 换成 async,yield换成 await,且不需要像Generator多次调用,async会自动执行并输出结果(返回Promise)
- 参考
- 内部多个耗时函数同时进行
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
- 错误处理
async function f() {await Promise.reject('出错了');await Promise.resolve('hello world'); // 不会执行
}async function f() {await Promise.reject('出错了').catch(e => console.log(e));return await Promise.resolve('hello world');
}f()
.then(v => console.log(v))
// 出错了
// hello world
UI 组件
定义和使用style
import React from 'react';
import {StyleSheet, Text, View} from 'react-native';const LotsOfStyles = () => {return (<View style={styles.container}><Text style={styles.red}>just red</Text><Text style={styles.bigBlue}>just bigBlue</Text><Text style={[styles.bigBlue, styles.red]}>bigBlue, then red</Text><Text style={[styles.red, styles.bigBlue]}>red, then bigBlue</Text></View>);
};const styles = StyleSheet.create({container: {marginTop: 50,},bigBlue: {color: 'blue',fontWeight: 'bold',fontSize: 30,},red: {color: 'red',},
});export default LotsOfStyles;
宽度和高度
- 、支持宽度和百分比
import React from 'react';
import { View } from 'react-native';const FixedDimensionsBasics = () => {return (<View><View style={{width:'50%', height: 50, backgroundColor: 'powderblue'}} /><View style={{width: 50, height: 100, backgroundColor: 'skyblue'}} /></View>);
};export default FixedDimensionsBasics;
- 弹性百分比宽高
import React from 'react';
import { View } from 'react-native';const FlexDimensionsBasics = () => {return (// 试试去掉父View中的`flex: 1`。// 则父View不再具有尺寸,因此子组件也无法再撑开。// 然后再用`height: 300`来代替父View的`flex: 1`试试看?<View style={{flex: 1}}><View style={{flex: 1, backgroundColor: 'powderblue'}} /><View style={{flex: 1, backgroundColor: 'skyblue'}} /><View style={{flex: 2, backgroundColor: 'steelblue'}} /></View>);
};export default FlexDimensionsBasics;
FlexBox
属性 | 描述 | 示例值 |
---|---|---|
flex | 定义了一个元素在容器中占据的空间比例。如果所有子元素的flex 值都为1,则它们将等分父容器的空间。 | 1 , 2 , 3 |
flexDirection | 定义了主轴的方向,即子元素的排列方向。 | 'row' (默认值,水平方向), 'row-reverse' (水平反向), 'column' (垂直方向), 'column-reverse' (垂直反向) |
flexWrap | 定义了当子元素超出容器宽度时是否换行。 | 'wrap' (换行), 'nowrap' (默认值,不换行), 'wrap-reverse' (换行并反向排列) |
justifyContent | 定义了子元素在主轴上的对齐方式。 | 'flex-start' (默认值,起始端对齐), 'flex-end' (末尾端对齐), 'center' (居中对齐), 'space-between' (两端对齐,项目之间的间隔平均分布), 'space-around' (项目两侧的间隔平均分布), 'space-evenly' (项目之间的间隔和项目与容器边界的间隔都相等) |
alignItems | 定义了子元素在交叉轴上的对齐方式。 | 'stretch' (默认值,如果项目未设置高度或设为auto,将占满整个容器的高度), 'flex-start' (交叉轴的起点对齐), 'flex-end' (交叉轴的终点对齐), 'center' (交叉轴的中点对齐), 'baseline' (项目的第一行文字的基线对齐) |
alignSelf | 允许单个子元素有与其他子元素不一样的对齐方式,可覆盖alignItems 属性。 | 'auto' (默认值,继承父元素的alignItems 属性), 'stretch' , 'flex-start' , 'flex-end' , 'center' , 'baseline' |
alignContent | 定义了多行子元素在交叉轴方向上的对齐方式,类似于justifyContent 但作用于垂直方向(当flexDirection 为column 时)或水平方向的多行(当flexDirection 为row 时)。 | 'stretch' (默认值,各行将会伸展以占据剩余的空间), 'flex-start' , 'flex-end' , 'center' , 'space-between' , 'space-around' , 'space-evenly' |
触摸组件
组件名称 | 描述 | 常用属性 | 示例场景 |
---|---|---|---|
TouchableWithoutFeedback | 触摸无反馈,仅触发功能或动作。 | onPress , onLongPress , disabled | 触发弹窗、跳转页面等无需视觉反馈的场景。 |
TouchableHighlight | 触摸时背景变暗,提供视觉反馈。 | onPress , onLongPress , underlayColor , disabled | 列表项、按钮等需要明确点击反馈的场景。 |
TouchableOpacity | 触摸时降低透明度,柔和的视觉反馈。 | onPress , onLongPress , activeOpacity , disabled | 图标、按钮等需要柔和点击反馈的场景。 |
TouchableNativeFeedback | Android特有,触摸时产生水波纹效果。 | onPress , onLongPress , background , disabled | Android平台上需要原生触摸反馈的场景。 |
常用交互
<ButtononPress={() => {Alert.alert('你点击了按钮!');}}title="点我!"
/>
Redux
一个状态管理容器,理解为可以用于在react-natvie 上使用的实现MVVM框架,“提供可预测化的状态管理”
基础概念
- Action :“View”的超集,用于将数据从应用传递到Store,是Store的唯一数据来源;约定必须使用字符串类型的
type
字段来标识action,也可以通过index
字段去标识。需要尽量减少在action的数据传递,可以用index代替。 - Reducer :可以理解为一个根据action去更新state的转换器,即
(oldState,action) -> newStat
,业务复杂时可以拆分多个reducer,通过combineReducers
方法返回一个聚合的reducer并注册到store
中。 - Store :Action是描述发生了什么,reducer是描述如何根据action去改变state,而store则是将这二者结合起来,可以定义多个reducer,使用 combineReducers() 将多个 reducer 合并成为一个。现在我们将其导入,并传递 createStore()。
方法名 | 描述 |
---|---|
getState() | 返回当前的 state 对象。 |
dispatch(action) | 分发一个 action 来触发 state 的变化。 |
subscribe(listener) | 添加一个变化监听器,每当 dispatch(action) 被调用时会执行。 |
replaceReducer(nextReducer) | 替换 store 当前用来计算 state 的 reducer。 |
与安卓通信
参考
- 官网与安卓交互教程
相关类
类/接口 | 功能 | 常用方法 | 备注 |
---|---|---|---|
ReactApplication | Application 需要实现的接口,返回一个 <font style="color:rgb(51, 51, 51);">ReactNativeHost</font> 对象 | <font style="color:rgb(51, 51, 51);">ReactNativeHost getReactNativeHost()</font> | |
ReactNativeHost | 持有<font style="color:rgb(51, 51, 51);">ReactInstanceManager</font> 和 安卓 <font style="color:rgb(51, 51, 51);">Application</font> 的一个实例,全局唯一;提供支持的 <font style="color:rgb(51, 51, 51);">ReactPackage</font> 列表以及RN Bundle文件名等 | <font style="color:rgb(51, 51, 51);">List<ReactPackage> getPackages()</font> | |
ReactPackage | 为RN提供原生能力的主要接口,包括各类 <font style="color:rgb(51, 51, 51);">NativeModule</font> 和 <font style="color:rgb(51, 51, 51);">ViewManagers</font> | <font style="color:rgb(51, 51, 51);">createViewManagers(ReactApplicationContext reactContext);</font> <font style="color:rgb(51, 51, 51);">createNativeModules(ReactApplicationContext reactContext)</font> | |
NativeModule | 封装的对RN提供能力的一个个原生模块,一般会继承<font style="color:rgb(51, 51, 51);">ReactContextBaseJavaModule</font> 进行实现。需要返回模块名称,方法通过 <font style="color:rgb(51, 51, 51);">ReactMethod</font> 注解提供 | <font style="color:rgb(51, 51, 51);">ReactContextBaseJavaModule#getCurrentActivity()</font> <font style="color:rgb(51, 51, 51);">String getName()</font> | JS调用示例:const {MyModule} = ReactNative.NativeModules; |
ViewManager | 封装的对RN提供原生View的一个类,一般会继承<font style="color:rgb(51, 51, 51);">ViewGroupManager</font> | 获取名称:<font style="color:rgb(51, 51, 51);">getName()</font> 返回实例: <font style="color:rgb(51, 51, 51);">createViewInstance</font> | |
ReactApplicationContext | 继承自 <font style="color:rgb(51, 51, 51);">ContextWrapper</font> ,与 <font style="color:rgb(51, 51, 51);">ReactContext</font> 基本一样 | ||
ReactContextReactApplicationContext | 继承自 <font style="color:rgb(51, 51, 51);">ContextWrapper</font> ,封装activity或者application;分发宿主生命周期事件继承自 <font style="color:rgb(51, 51, 51);">ContextWrapper</font> ,与 <font style="color:rgb(51, 51, 51);">ReactContext</font> 基本一样 |
注解等
注解 | 功能 | 常用方法 |
---|---|---|
ReactMethod | 标记此方法为对RN提供 | isBlockingSynchronousMethod: 标记是否为同步方法 |
构建打包
示例
- 直接构建:
npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
- 直接使用本地的 cli版本:
node ./node_modules/react-native/local-cli/cli.js bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
常用参数
参数 | 描述 | 示例值 |
---|---|---|
--platform | 指定目标平台 | android 或 ios |
--dev | 设置为false 以生成生产环境的bundle包(不包含调试信息),设置为true 则包含调试信息 | false 或 true |
--entry-file | 指定应用的入口文件 | index.js 或 App.js |
--bundle-output | 指定bundle包的输出文件路径 | 对于Android: android/app/src/main/assets/index.android.bundle 对于iOS: ios/main.jsbundle |
--assets-dest | 指定资源文件(如图片和字体)的输出目录 | 对于Android: android/app/src/main/res/ 对于iOS: ios/ (但iOS通常会将资源文件放入ios/bundle/Release/ 或ios/bundle/Debug/ 等目录,具体取决于构建配置) |
--minify | 启用代码压缩(注意:从React Native 0.57开始,当--dev 为false 时,默认启用) | true (但在--dev false 时通常不需要显式指定) |
自定义RN插件
- 可以设置
ContentView
为ReactRootView
- 自定义加载bundle路径,bundle依赖的资源是相对路径,将构建出来的资源文件一起放到对应位置即可
ReactInstanceManager.builder().setApplication(application).setJSBundleFile(jsBundlePath).setJSMainModulePath(entryFile).setUseDeveloperSupport(isDebug).setIsMultiRnRender(isMultiRender).setInitialLifecycleState(lifecycleState)