当前位置:网站首页 > React Native移动开发 > 正文

React Native开发速记_react native 开发

引子

软件开发,移动优先;移动开发,RN优先。为什么?RN的性能胜任大部分应用场景,开发效率奇高(前提当然是熟悉web和javascript),热更新,快速见效,出活快,画一个界面三言两语,比原生简洁多了。Flutter? Xamarin? NativeScript? Ionic? Cordova? 我还是选RN。有人担心RN不流行了,会被替代,大可不必,哪种技术能长命百岁?一个产品有三五年的周期就算长寿了。RN短期内死不了。新的JS引擎 Hermes也极大地改进了性能。

经过一段时间的使用,笔者发现:RN代码好写,但小问题不少,一方面是RN本身的问题,另一方面文档不细。

React常见的问题是状态管理,例如嵌套组件之间的状态传递。setState()后数据未及时更新,不得不利用useEffect()做数据的提交。

React Native适用场景

大部分应用都可以采用RN,新闻资讯类自不必说,电商类,教育类,视频播放类,也不在话下。CPU密集型?游戏类?这个我没有尝试过。但就像Java和C++/C的关系一样,80~90%都可以由Java搞掂,剩下的C来搞掂。你能吃下90%的业务部分,你还担心什么?

在这里插入图片描述

工具前提

必须安装的依赖有:Node、Watchman、Xcode 和 CocoaPods。CocoaPods是用 Ruby 编写的包管理器(可以理解为针对 iOS 的 npm)。从 0.60 版本开始 react native 的 iOS 版本需要使用 CocoaPods 来管理依赖。你可以使用下面的命令来安装 CocoaPods。CocoaPods 的版本需要 1.10 以上。所以你又得先装rvm和ruby。

React基础

TODO

JSX

JSX 是 React 的核心组成部分,它使用 XML 标记的方式去直接声明界面。JSX貌似丑陋,和JS代码耦合,但其背后的哲学是每个HTML都是由有生命的片段组合而成,有了对片段的良好编程,就能由简到繁,积小成大,去构建更庞大的应用。

JSX的一大好处就是容易组合:

function func1() {
   
	return <View>func1</View>
}
function func2() {
   
	return <View>func2</View>
}
function func3() {
   
    // 多行要用小括号包起来!
	return (<View>
	        {
   func1()}
	        {
   func2()}
	     </View>)
}

这样就比较容易构造复杂的组件。
一个典型的写法:

function doRender() {
   
	return (
		<View>
	         {
   list.map(item => (
	           <Section item={
   item} />
	         ))}
		</View>
	)
}

组件的定义

组件:拥有props和state,和render()函数的对象。
单向数据流(one-way flow of data)是React程序的一大特点。
组件有两种写法:类组件和函数式组件。
类的写法:

class Welcome extends React.Component {
   
  render() {
   
    return <h1>Hello, {
   this.props.name}</h1>;
  }
}

函数写法:

function Welcome(props) {
    
  const data = [
    {
    id: 1, name: "John Doe" },
    {
    id: 2, name: "Victor Wayne" },
    {
    id: 3, name: "Jane Doe" },
  ];
  return (
  	<View>
	  	<Text>Hello, {
   props.name}</Text>
	    <View className="users">
	      {
   data.map((user) => (
	        <Text className="user">{
   user}</Text>
	      ))}
	    </View>
    </View>
  );
}

函数组件就是可以返回一个ReactElement的函数。

高阶组件(HOC)

React高阶组件(HOC), 是一个参数为组件,返回值也是一个组件的函数。
在这里插入图片描述

生命周期函数与组件渲染

几个常用的生命周期函数:componentDidMount,componentDidUpdate 和 componentWillUnmount,在组件不同阶段被调用。

渲染:通过Javascript API修改DOM对象谓之渲染,如document.write、Node.appendChild或Element.setAttribute等DOM编程接口。

当VDOM更新了,React将其与之前的VDOM快照进行比较,然后仅更新真实DOM中发生更改的内容。如果没有任何改变,真正的DOM根本不会更新。

React DevTools允许我们在Components -> View Settings -> Highlight updates中设置渲染时高亮更新。这将展示所有虚拟渲染。

如果我们想看原生重渲染,我们需要在Chrome DevTools中三个点的菜单-> More tools -> Rendering -> Paint flashing。

每当组件的状态发生变化时,React都会调度一次渲染。调度渲染并不意味着渲染过程会立即发生。 React将尝试为此找到最佳时机去执行这个操作。

通常采用setState函数来渲染组件。
props发生了变化,未必会导致组件渲染。而且,不要直接改变props对象,如this.props.user.name = ‘Felix’;
因为这不会触发任何更改,并且React不会注意到这些更改。

组件的缺省属性

react 提供了语法糖:defaultProps,可以实现属性的混合。

import React from 'react'
// 函数组件
export default function FuncDefault(props) {
   
    console.log(props);//已经完成了混合
    return (
        <div>
            a:{
   props.a},b:{
   props.b},c:{
   props.c}
        </div>
    )
}
//属性默认值
FuncDefault.defaultProps = {
   
    a: 1,
    b: 2,
    c: 3
}

// 类组件
export default class ClassDefault extends React.Component {
   
	constructor(props) {
   
        super(props);
        console.log(props);
    }
}
ClassDefault.defaultProps = {
   
	a:1, b:2, c:3
}

组件之间的通信

  • 父组件传属性给子组件,属性变,子组件也跟着变。
  • 父组件通过useRef()获得子组件的引用,然后调用子组件的方法。
  • useImperativeHandle(ref,createHandle,[deps])可以自定义暴露给父组件的实例值。如果不使用,父组件的ref(chidlRef)访问不到任何值(childRef.current==null)
  • useImperativeHandle应该与forwradRef搭配使用;React.forwardRef会创建一个React组件,这个组件能够将其接受的ref属性转发到其组件树下的另一个组件中。
    React.forward接受渲染函数作为参数,React将使用prop和ref作为参数来调用此函数。
  • 子组件想通知父组件,可以通过调用父组件传递过来的函数,这个函数也是通过props传递的。
  • 任意两个组件之间通过消息进行通信。
// 发送方
DeviceEventEmitter.emit('sendMsg', {
   text:'Hello'});
// 接收方
DeviceEventEmitter.addListener('sendMsg',function(params){
   
     // do something with the params
});

基础API

在这里插入图片描述

在这里插入图片描述
ReactNode是一个联合类型:

type ReactNode =
  | ReactChild
  | ReactFragment
  | ReactPortal
  | boolean
  | null
  | undefined;
type ReactText = string | number;
type ReactChild = ReactElement | ReactText;

Flex弹性布局

定理采用Flex加上嵌套能实现任意布局

  • react 宽度基于pt为单位, 可以通过Dimensions 来获取宽高,PixelRatio 获取密度。运行在Android上时,View的长和宽被解释成:100dp 100dp单位是dp,字体被解释成16sp 单位是sp,运行在iOS上时尺寸单位被解释称了pt,这些单位确保了布局在任何不同dpi的手机屏幕上显示不会发生改变

  • 基于flex的布局

    • view默认宽度为100%
    • 水平居中用alignItems, 垂直居中用justifyContent
    • 基于flex能够实现现有的网格系统需求,且网格能够各种嵌套无bug
  • 图片布局

    • 通过Image.resizeMode来适配图片布局,包括contain, cover, stretch
    • 默认不设置模式等于cover模式
    • contain模式自适应宽高,给出高度值即可
    • cover铺满容器,但是会做截取
    • stretch铺满容器,拉伸
  • 定位

    • 定位相对于父元素,父元素不用设置position也行
    • padding 设置在Text元素上的时候会存在bug。所有padding变成了marginBottom
  • 文本元素

    • 文字必须放在Text元素里边
    • Text元素可以相互嵌套,且存在样式继承关系
    • numberOfLines 需要放在最外层的Text元素上,且虽然截取了文字但是还是会占用空间

例子: Flex布局实现多行多列

容器: flex-wrap: wrap; 允许折行
元素有三种方式:

  • flex: 1 0 33.3%;
  • flex-basis: 33.3%;
  • width: 33.3%;

和Web CSS上FlexBox的不同之处

  • flexDirection: React Native中flexDirection:'column’对应Web CSS的flex-direction:‘row’
  • alignItems: React Native中alignItems:'stretch’对应Web CSS的align-items:‘flex-start’
  • flex: 相比Web CSS的flex接受多参数,如:flex: 2 2 10%;,但在 React Native中flex只接受一个参数
  • 不支持属性:align-content,flex-basis,order,flex-basis,flex-flow,flex-grow,flex-shrink

常用UI组件

RN UI 组件 Android View iOS View
View ViewGroup UIView
Text TextView UITextView
Image ImageView UIImageView
ScrollView ScrollView UIScrollView
TextInput EditText UITextField
??? RecyclerView UITableView

1、View是最核心、最常用的UI组件,包罗万象。几乎总是和{flex:1}搭配,否则空白。
2、FlatList长列表组件,可以实现下拉刷新和上拉加载。FlatList没有对应的原生组件,其实现是基于ScrollView。VirtualizedList是FlatList和SectionList的底层实现。FlatList和SectionList都依赖一个数组,每个元素是个字典,SectionList的字典必须有data、title、key。注意:不要在ScrollView里使用FlatList。开源世界还有个FlashList,据说是FlatList替代品,性能更高。
3、WebView,显示html文档。
4、导航器
5、富文本编辑器: wxik/react-native-rich-editor和https://github.com/imnapo/react-native-cn-richtext-editor

UI基本示例:

 <View style={
       {
       flex: 1}} >
    <ScollView style={
       {
       flexGrow: 1}} nestedScrollEnabled={true}>
        <View>
            <SafeAreaView>
                <ScrollView horizontal style={
       {
       width: '100%', height: 'your_height'}}>
                  {data.map((item, index) => (
                    <View key={index}>
                      // Your component
                    </View>
                  ))}
                </ScrollView> -- Horizontal Scroll --
            </SafeAreaView>
        </View>        
    </ScrollView>
</View>

React Hook

Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。Hooks 是一种在函数式组件中使用有状态函数的方法。Hooks不支持在class中使用,比如在class中使用useState和useEffect都是不允许的。

Hooks 只能在顶层调用,不要在循环,条件或嵌套函数中调用 Hook。原因是 React 需要保证每次组件渲染的时候都以相同的顺序调用 Hooks。

主要的Hook

  • useEffect()函数:作用就是指定一个副效应函数,组件每渲染一次,该函数就自动执行一次。组件首次在网页 DOM 加载后,副效应函数也会执行。它的第二个参数,使用一个数组指定副效应函数的依赖项,只有依赖项发生变化,才会重新渲染。
  • useState()函数:用于为函数组件引入状态。
  • useContext():用于在组件之间共享状态。
  • useReducer():React 本身不提供状态管理功能,通常需要使用外部库。这方面最常用的库是 Redux。Redux 的核心概念是,组件发出 action 与状态管理器通信。状态管理器收到 action 以后,使用 Reducer 函数算出新的状态,Reducer 函数的形式是(state, action) => newState。
  • useImperativeHandle(): 快速对外暴露接口
Hook函数 说明
useState [<取值>, <设值>] = useState(<初始值>),useState可以保存状态,在状态改变的时候重新渲染视图,而普通变量会被重新赋值,无法保存状态
useEffect 在组件加载和监听的对象值发生变化时调用;第二个参数是数组,只要其中一个发生变化,React 都会执行指定函数
useImperativeHandle 对外暴露接口
useContext 多层嵌套组件之间共享状态,无论它们在组件树中的深度如何
useLayoutEffect
useReducer const [state, dispatch] = useReducer(reducer, initialArg, init)
useCallback 在依赖不变的情况下不返回新的函数地址而返回旧的函数地址。在往子组件传入了一个函数并且子组件被React.momo缓存了的时候使用
useMemo 用于进行计算属性的计算,当依赖列表变化时重新计算,类似与Vue的computed()函数
useRef 返回一个mutable ref对象,用.current获得其值。每次渲染 useRef 返回值都不变;ref.current 发生变化并不会造成 re-render;
useTransition
useDeferredValue
useId

useState用法

  • useState的更新是异步的,数据不会立即刷新的。其背后是队列实现的。通过useEffect()可以观察到其值的变化。
  • 仅顶层调用,不能在循环,条件,嵌套函数等中调用useState()。
  • 通过set方法修改状态时,只有引用发生变化,才会导致组件重绘。此点非常关键,下面针对几种情形分别举例。

修改对象:

const [user, setUser] = useState({
   
	username: "",
    password: "",
 })
const handleChange = (e) => 
    setUser(prevState => ({
   ...prevState, [e.target.name]: e.target.value}))

不要直接:

setUser({
   ...prevState, [e.target.name]: e.target.value})

修改数组:

const [todos, setTodos] = useState([])
setTodos(preState => ([{
   
          id: todos.length,
          text: text
        }, ...preState]));

修改boolean数组:

const [boolState, setBoolState] = useState(Array(10).fill(false)) //初始数组为长度为10的布尔数组
const toogleState = (index) => {
   
    setBoolState(prevState => prevState.map((item, idx) => idx === index ? !item : item))
};

修改ES6的Map:

const [myMap, setMyMap] = useState(new Map());
const updateMap = (k,v) => {
   
  setMyMap(new Map(myMap.set(k,v)));
}

useEffect典型用法

const [data, setData] = useState()
useEffect(() => {
   
  // declare the async data fetching function
  const fetchData = async () => {
   
    // get the data from the api
    const data = await fetch(`https://yourapi.com?param=${
     param}`);
    // convert the data to json
    const json = await response.json();
    // set state with the result
    setData(json);
  }

  // call the function
  fetchData()
    // make sure to catch any error
    .catch(console.error);;
}, [param])

再举一个例子:

import {
    useState, useEffect } from 'react';

const HackerNewsStories = () => {
   
  const [stories, setStories] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
   
    const fetchStories = async () => {
   
      try {
   
        const data = await (await fetch('https://hn.algolia.com/api/v1/search_by_date?tags=front_page&hitsPerPage=20')).json();
        setStories(
          data.hits.sort((story, nextStory) => (story.points < nextStory.points ? 1 : -1)) ); setError(null); } catch (err) {
      setError(err.message); setStories(null); } finally {
      setLoading(false); } }; fetchStories(); }, []); return ( <div className="wrapper"> <h2>Latest HN Stories</h2> {
     loading && <div>HackerNews frontpage stories loading...</div>} {
     error && <div>{
     `Problem fetching the HackeNews Stories - ${
       error}`}</div>} <div className="stories-wrapper"> {
     stories && stories.map(({
      objectID, url, title, author, points }) => (
            title && url &&
            <div className='stories-list' key={
   objectID}>
              <h3><a href={
   url} target="_blank" rel="noreferrer">{
   title}</a> - By <b>{
   author}</b> ({
   points} points)</h3>
            </div>                        
          ))}
      </div>
    </div>
  );
};

export default HackerNewsStories;

useRef与forwardRef

使用函数式组件时,需要注意useRef的使用。

Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

const InputText = React.forwardRef((props, ref) => (
 <input ref={
   ref} {
   ...props} />
));
import * as React from "react";
import ReactDOM from "react-dom";

const InputText = React.forwardRef((props, ref) => (
 <input ref={
   ref} {
   ...props} />
));

export default function App() {
   
 const ref = React.useRef();

 function focus() {
   
   ref.current.focus();
 }

 return (
   <div className="App">
     <InputText ref={
   ref} placeholder="my input" />
     <button onClick={
   focus}>Focus</button>
   </div>
 );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

使用Redux

Redux首先是一种设计模式,然后才有各种实现库。解决什么问题呢?主要针对复杂的应用,这些应用中有大量的各种状态,行为,操作方,为了管理这些状态和操作,便诞生了redux。
在这里插入图片描述
基本处理过程是:
1、界面事件产生action,action是type+payload,然后发送出去(dispatch),如dispatch({type: ‘counter/increment’})
2、store运行reducer函数处理action,处理完返回一个新的state
3、store通知所有订阅该store的UI,UI根据新的state重新绘制
翻译成代码示例:

// 1) 使用 `createStore` 函数创建 Redux store
const store = Redux.createStore(counterReducer)

// 2) 订阅更新(以便将来数据更改时能够重绘)
store.subscribe(render)

// 我们的“用户界面”是单个 HTML 元素中的一些文本
const valueEl = document.getElementById('value')

// 3) 当订阅回调函数运行时:
function render() {
   
  // 3.1) 获取当前 store 的 state
  const state = store.getState()
  // 3.2) 提取你想要的数据
  const newValue = state.value.toString()

  // 3.3) 使用新值更新 UI
  valueEl.innerHTML = newValue
}

// 4) 使用初始 state 渲染 UI
render()

// 5) 基于 UI 输入 dispatch action
document.getElementById('increment').addEventListener('click', function () {
   
  store.dispatch({
    type: 'counter/incremented' })
})

总而言之,UI基于State, state存放在store中,通过redux函数修改state,通过dispatch函数发送state,这是React和Redux的基本哲学,也是我们使用React的要点。设计好你的state,整个应用程序所需的全局 state 应该放在 Redux store 中。只在一个组件内使用的 state 应该放在组件 state 中。

组件和Store的如何关联?

  • 使用useSelector(),每次调用useSelector会从store中返回state数据。且store中state数据发生变化,会通知到组件
  • 使用Provider。使用 <Provider store={store}> 组件包裹 <App>,这样使其他 React 组件可以和 store 进行交互
  • 使用connect()函数。
const mapStateToProps = state => {
   
  return {
   
      notes: state.notes
  }
}

// connect with redux,first param is map and second is component
export default connect(mapStateToProps)(AddNote)

和原生模块交互

在使用 React 做开发时有两种写法:
类组件
函数组件 + Hook (用的这种)
React 组件之间共享数据的方案:
使用 React 自带的 Context + Reducer 功能 (用的这种)
优点:无须引入其他的包
缺点:只能向子组件及子孙组件中共享数据
使用 Redux 实际组件之间的共享
优点:数据全都放到 Redux 中管理,无论什么层级都直接使用
缺点:需要单独安装,数据状态由它统一管理,很多代码写法不太一样
RN 中的布局
View 组件默认是相对定位的(可以直接使用 left 、top 相对于原来的位置定位)
View 组件的绝对定位都是相对于父组件定位的(因为父组件都是相对定位,所以默认都是子绝父相)
没有浮动,只能 flex
父组件一定要设置高度或者 flex:1 ,否则高度为0页面空白

调用原生模块方法:
要实现一个自己的ReactPackage和ReactModule,在ReactModule中暴露js方法。

Realm数据库

目前主要有Realm、Firebase、PouchDB、Async Storage、WCDB(腾讯开源)与SQLite等。
推荐使用Realm,realm已经被MongoDB收购,成为移动端首选。

在这里插入图片描述

Realm使用基础
安装: yarn add realm @realm/react
文件真机路径: data/data/包名/files/xxx.realm
工具: Realm Studio,能查看realm文件中的数据
参考:https://github.com/mongodb/template-app-react-native-todo

realm有三个钩子函数: useRealm(), useObject()和useQuery(),其中useQuery()能随着后台数据的刷新而刷新。

调试

调试方面强烈推荐使用 React Native Debugger,一个基于 React Native 官方调试方式、包含 React Inspector / Redux DevTools 独立应用:

  • 基于官方的 Remote Debugger 且提供了更为丰富的功能
  • 包含 react-devtools-core 的 React Inspector
  • 包含 Redux DevTools, 且与 redux-devtools-extension 保持 API 一致

命令行

  • react-native
    通过 react-native bundle 命令可对当前 RN 项目进行打包,以 iOS 为例
react-native bundle --platform ios --dev false \
   --entry-file index.js \
   --bundle-output __test__/example/index.ios.jsbundle \
   --assets-dest __test__/example/

多个jsBundle异步加载

每个ReactApplication可以加载一个js bundle,如果将index.android.bundle拆成多个包,就得写多个ReactApplication。
每个ReactApplication对应一个ReactActivity,每个ReactActivity对应一个MainComponentName,即在js里注册的组件名称。

Metro

metro 是一个针对 React Native的JavaScript模块打包器,他接收一个entry file (入口文件) 和一些配置作为参数,返回给你一个单独的JavaScript文件,这个文件包含了你写的所有的JavaScript 代码和所有的依赖。
也就是说Metro把你写的几十上百个js文件和几百个node_modules的依赖,打包成了一个文件。

打包

一种是采用IDE(Android Studio或xcode),一种是直接用Expo提供的EAS命令行工具。当然,安卓应用直接采用gradle命令行打包也是可以的。

也可以本地打包:

npx expo run:android
npx expo run:ios

Android

不要用Android Studio打包,直接用命令:

./gradlew assembleRelease
需要在gradle配置文件中添加签名配置

iOS

iOS上打包有两种方式:React Native CLI 和 Expo,前者可定制性比较高,后者使用更复杂些。
主要操作就是想RN的一堆web资源打包成iOS项目能利用的bundle。

第一步,打包web资源

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

第二步,导入到iOS项目中
将JS部分的代码和图片资源等打包导出到release_ios目录下。选择assets文件夹与main.jsbundle文件将其拖拽到XCode的项目导航面板中即可。

修改AppDelegate.m文件:

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
   
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  //没有使用CodePush热更新的情况
// return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
  //如果在项目中使用了CodePush热更新,那么我们需要就可以直接通过CodePush来读取本地的jsbundle,方法如下: For React Native >=0.59,https://github.com/microsoft/react-native-code-push/blob/master/docs/setup-ios.md
  return [CodePush bundleURL];
#endif
}

Expo

测试

Expo为我们测试运行app提供了一种简单的方式,Expo能托管你的应用。当你执行yarn expo start启动应用后,扫码就能在手机上看到运行效果。你只管写纯JS的应用,它帮你构建部署到手机上,Android或iOS。它需要在你手机上安装一个应用Expo Go,然后你开发的Expo应用就被Expo Go托管,就像小程序和微信的关系。

expo 提供了四种工具帮助我们更好地开发:

  • client 手机端 app,用于预览项目
  • expo-cli命令行工具,开发,构建,部署
  • snack 沙盒工具,实时编辑,在线预览
  • SDK 核心。版本号随 RN 版本号更新
    在这里插入图片描述

Expo is an open-source platform for making universal native apps that run on Android, iOS, and the web. It includes a universal runtime and libraries that let you build native apps by writing React and JavaScript.

Expo包含一个命令行工具Expo CLI和一个移动客户端Expo Go。在开发机器上,你只需要按照Nodejs环境即可,无需Android SDK和xcode这些编译环境。iOS 设备直接在 App Store 搜索并安装 expo go,Android 需要事先安装好 Android Play Store,然后搜索并安装 expo go。当安装完成之后,iOS 自带的Code Scanner应用扫码,Android 使用Expo Go内自带的扫码按钮,即可真机预览你开发的 app。
Expo Go只是给开发阶段用的,最后要发布产品时还得用Expo提供的工具打成apk和ipa包。

在这里插入图片描述

你可以在https://snack.expo.dev/上试用一下简单的例子。

打包

安装eas cli,然后运行下面命令打包:

eas build --platform all
eas build --platform android
eas build --platform ios

这样,在Expo的网站上能看到自己的app,扫码下载安装。

其它工具

  • Watchman, Watchman 在更改时观察文件和记录,然后触发相应的操作,并由 React Native 在内部使用

常用命令

npx react-native info

UI框架

其实RN提供的基本UI组件已经能实现大部分界面,但还有很多第三方UI库可供选择。

  • react native elements
  • react-native-elements
  • 蚂蚁金服 Ant Design Mobile RN
  • Lottie for React Native
  • NativeBase
  • React Native Material UI
  • react-native-ui-kitten
  • 雷数科技前端部门组件库/工具库

推荐阅读的开源项目

  • React-Native-Apps
  • F8: ReactNative作者们写的Conference App
  • 在线订餐系统YumMeals
  • 一款电影APP
  • github客户端
  • 流媒体音频app MindCast
  • iReading阅读器
  • https://github.com/stage88/react-weather
  • https://github.com/wwayne/react-native-nba-app
  • https://github.com/iSimar/HackerNews-React-Native
  • https://github.com/ljunb/react-native-iShiWuPai
  • https://github.com/BelinChung/react-native-hiapp

参考资源

  • https://github.com/jondot/awesome-react-native
  • https://github.com/reactnativecn/react-native-guide
  • Redux
  • 下载 Genymotion免费版
  • 多终端开发
  • 矢量图标库
  • js bridge的一个实现
  • devio技术博客
  • RNStudyNotes
  • react-native-sqlite-storage
  • Expo官网

版权声明


相关文章:

  • React Native Android混合开发实战教程2024-10-30 14:42:26
  • react native_微服务 落地完全实践2024-10-30 14:42:26
  • [译] 测试原生,Flutter 和 React Native 移动开发之间的性能差异2024-10-30 14:42:26
  • React Native Android混合开发实战教程,Android开发面试准备_react混合开发app2024-10-30 14:42:26
  • React Native跨平台移动应用学习与开发(二) 第一个项目2024-10-30 14:42:26
  • native react 电子书_React Native移动开发实战 (袁林著) 带目录完整pdf[146MB]2024-10-30 14:42:26
  • reactnative开源项目_react native环境搭建2024-10-30 14:42:26
  • React Native移动开发实战-3-实现页面间的数据传递2024-10-30 14:42:26
  • React-Native优质开源项目,详解2024-10-30 14:42:26
  • 深入解析三大跨平台开发框架:Flutter、React Native 和 uniapp_跨平台app开发框架首选2024-10-30 14:42:26
  • 全屏图片