购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.1 React Native框架及工作原理

React Native框架内部提供了很多的内置组件,如图3-1所示。包括基本组件,如View、Text等,用于一些功能布局的Button、Picker等,iOS平台与Android平台的特定组件、API等。同时也提供了接口便于与原生平台进行交互。后续的章节我们会介绍与原生平台的混合实战开发。

在介绍React框架的章节,我们理解了如何将代码渲染至虚拟DOM并更新到真实DOM的过程。在React Native框架中,渲染到iOS平台与Android平台的过程如图3-2所示。

图3-1 React Native框架构成

图3-2 React Native渲染

在React框架中,JSX源码通过React框架最终渲染到了浏览器的真实DOM中,而在React Native框架中,JSX源码通过React Native框架编译后,通过对应平台的Bridge实现了与原生框架的通信。如果我们在程序中调用了React Native提供的API,那么React Native框架就通过Bridge调用原生框架中的方法。

因为React Native的底层为React框架,所以,如果是UI层的变更,那么就映射为虚拟DOM后调用diff算法计算出变动后的JSON映射文件,最终由Native层将此JSON文件映射渲染到原生App的页面元素上,实现了在项目中只需控制state以及props的变更来引起iOS与Android平台的UI变更。

编写的React Native代码最终会被打包生成一个main.bundle.js文件供App加载,此文件可以存储在App设备本地,也可以存储于服务器上,以供App下载更新,后续章节讲解的热更新就会涉及main.bundle.js位置的设置问题。

3.1.1 React Native与原生平台通信

React Native在与原生框架通信中,如图3-3所示,采用了JavaScriptCore作为JS VM,中间通过JSON文件与Bridge进行通信。若使用Chrome浏览器进行调试,那么所有的JavaScript代码都将运行在Chrome的V8引擎中,与原生代码通过WebSocket进行通信。

图3-3 React Native与原生平台的通信

3.1.2 组件间通信

React Native开发最基本的元素就是组件,React Native与React一样,也会涉及组件之间的通信,便于数据在组件之间传递,下面列出了几种常用的组件间通信方式。

1.父子组件的通信

如同之前介绍React组件间参数传递一样,在React Native中,可以通过props的形式实现父组件向子组件传递值。

在下例中,父组件通过调用子组件并赋值子组件的name为React,子组件通过this.props.name获取父组件传递过来的name的字符串值React。

完整代码在本书配套源码的03-04文件夹。

 1. /** 
 2. * 章节: 03-04 
 3. * 父子组件通信,在父组件中调用子组件 
 4. * FilePath: /03-04/parent-2-child.js 
 5. * @Parry 
 6. */  
 7.  
 8. <ChildComponent name='React'/>  
 9.  
10. /** 
11. * 章节: 03-04 
12. * 子组件实现,通过 props 获取父组件传递的值
13. * FilePath: /03-04/parent-2-child.js 
14. * @Parry 
15. */  
16.  
17. class ChildComponent extends Component {  
18.   render() {  
19.     return (  
20.       <Text>Hello {this.props.name}!</Text>
21.     );
22.   }
23. }
2.子父组件的通信

在开发过程中,还会有子组件向父组件通信传递值的需求,比如当子组件的某个值变更后,需要通知到父组件做相应的变更与响应,那么就需要子父组件之间的通信。

例如,在父组件的定义中,在调用子组件时,同样向子组件传递了一个参数,不过这个参数是一个函数,此函数用于接收后续子组件向父组件传递过来的数据,与之前父组件向子组件传递数据不太一样。

完整代码在本书配套源码的03-04文件夹。

 1. /** 
 2. * 章节: 03-04 
 3. * 子父组件通信,父组件的实现 
 4. * FilePath: /03-04/child-2-parent.js 
 5. * @Parry 
 6. */  
 7. import React, {Component} from 'react';  
 8. import ChildComponent from './ChildComponent'  
 9.   
10. class App extends Component {  
11.   constructor(props) {  
12.     super(props)  
13.     this.state = {  
14.       name: 'React'  
15.     }  
16.   }  
17.   
18.   //传递到子组件的参数,不过参数是一个函数。  
19.   handleChangeName(nickName) {  
20.     this.setState({name: nickName})  
21.   }  
22.   
23.   render() {  
24.     return (  
25.       <div>  
26.         <p>父组件的 name:{this.state.name}</p>  
27.         <ChildComponent  
28.           onChange={(val) => {  
29.           this.handleChangeName(val)  
30.         }}/>  
31.       </div>  
32.     );  
33.   }  
34. }  
35.   
36. export default App;

下面为子组件的定义,子组件在页面中定义了一个按钮,点击此按钮调用自身的一个函数handleChange,修改了自身state中的值name为nickName定义的值Parry,那么此子组件的页面上的字符串将由之前的Hello React!变为Hello Parry!,同时使用了this.props.changeName,也就是父组件调用时传递过来的函数,向父组件传递了nickName的值Parry。

父组件在接收到子组件的调用后,调用了父组件自身的函数handleChange Name修改了自身的state中的name的值为Parry,也就是子组件传递过来的Parry,所以,父组件的页面上的值也同时由之前的React变更成了Parry。代码如下:

 1. /** 
 2. * 章节: 03-04 
 3. * 子父组件通信,子组件的实现 
 4. * FilePath: /03-04/child-2-parent.js 
 5. * @Parry 
 6. */  
 7.   
 8. import React, {Component} from 'react'  
 9.   
10. export default class ChildComponent extends Component {  
11.   constructor(props) {  
12.     super(props)  
13.   
14.     this.state = {  
15.       name: 'React'  
16.     }  
17.   }  
18.   
19.   handleChange() {  
20.     const nickName = 'Parry';  
21.     this.setState({name: nickName})  
22.     //调用父组件传递过来的函数参数,传递值到父组件去。  
23.     this  
24.       .props  
25.       .changeName(nickName)  
26.   }  
27.   
28.   render() {  
29.     const {name} = this.state;  
30.     return (  
31.       <div>  
32.         <p>Hello {name}!</p>  
33.         <Button  
34.           onPress={this  
35.           .handleChange  
36.           .bind(this)}  
37.           title="修改一下 name 为 Parry"/>  
38.       </div>  
39.     )  
40.   }  
41. }  
3.多级组件之间的通信

如果组件之间的父子层级非常多,需要进行组件之间的传递,这时候当然可以通过上面介绍的方法逐级传递,但这样的传递方法不是一个太好的方法。

因为组件之间通信冗长,嵌套逻辑太深,会导致用户体验不好,可以想象一下用户从最底层一层层操作返回到最顶层时的体验。

可以使用如context对象或global等方式进行多级组件间的通信,但是不推荐这种方式。最好不要让组件之间的层级关系太深。

4.无直接关系组件间通信

前面提到的都是有层级关系的组件间的通信方式,如果组件间没有层级关系的话,则可以通过如AsyncStorage或JSON文件等方式进行通信。

当然,还可以使用EventEmitter/EventTarget/EventDispatcher继承或实现接口的方式、Signals模式或Publish/Subscribe的广播形式,都可以达到无直接关系组件间的通信。

这些组件间的通信方式使得组件之间可以传递数据,后续的实战章节会有详细的代码实现,这里主要进行了理论的介绍。掌握这部分知识后才可以将App开发中的基本单位(也就是组件)串联起来。 vx1cD1d+GFqW5ByY0wPGvY05PGEOJqr4giSEIB9PyicPyJDOFAluTS3RE29cIEW7

点击中间区域
呼出菜单
上一章
目录
下一章
×