React Native学习速记

学习路线建议:ES5/6 -> React -> React Native  -> Redux + React-Navigation等

1、RN环境配置与运行

  • 按照官网进行环境配置;
  • 配置完成,初始化项目:react-native init 项目名称(注意 - 可以cd到自己目录,比如D:/RN目录下,然后执行该命令,即可在该目录下初始化自己的RN项目了,不要在系统或其他需要权限的目录,因为这会导致一些奇怪的问题发生
  • 运行项目:react-native run-android
  • 学习的时候,如果高版本的RN常见运行有问题,可尝试低版本。项目开发建议使用最新版本RN
  • 安装第三方库,使用npm有时候莫名报错,可使用yarn尝试安装

2、调试

开发RN推荐开发工具VsCode。

有两种方式可以进行RN的调试,任选其一即可。(调试要确保在同一个网段内进行,切记)

  • 使用VSCode进行调试

a)需要安装,安装React Native Tools插件。

b)安装完成之后,通过react-native run-android命令,将项目运行到真机跑起来。

c)配置调试选项,如下图:

d)唤出开发者菜单,配置当前的ip和端口;

e)点击调试按钮即可进行调试;

  • 使用Chrome浏览器调试

项目跑起来之后,唤出开发者菜单,打开Debug Js Remotely即可。注:如果在Chrome中调试,出现跨域等问题,试着将ip改成localhost即可。

3、React相关

组件是根据props进行渲染的。state是组件的内部状态,目前,React Native 可以使用redux进行状态的管理。

JSX --> 通过Babel转义为纯JS代码 --> 虚拟DOM(DOM DIFF) --> 真实DOM(执行完了render方法)

React Native 是React 在原生移动应用平台的衍生产物,那两者主要的区别是什么呢?其实,主要的区别在于虚拟DOM映射的对象是什么?React中虚拟DOM最终会映射为浏览器DOM树,而RN中虚拟DOM会通过 JavaScriptCore 映射为原生控件树。

JavaScriptCore 是一个JavaScript解释器,它在React Native中主要有两个作用:

  1. 为JavaScript提供运行环境。
  2. 是JavaScript与原生应用之间通信的桥梁,作用和JsBridge一样,事实上,在iOS中,很多JsBridge的实现都是基于 JavaScriptCore 。

而RN中将虚拟DOM映射为原生控件的过程中分两步:

  1. 布局消息传递; 将虚拟DOM布局信息传递给原生;
  2. 原生根据布局信息通过对应的原生控件渲染控件树;

至此,React Native 便实现了跨平台。 相对于混合应用,由于React Native是原生控件渲染,所以性能会比混合应用中H5好很多,同时React Native是Web开发技术栈,也只需维护一份代码,同样是跨平台框架。

3.1、组件属性验证

组件的属性可以接受任何值,字符串、对象、函数等等都可以。有时,我们需要一种机制,验证别人使用组件时,提供的参数是否符合要求。组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求。

React.PropTypes从Reactv15.5开始被移入了prop-types组件库。

import PropTypes from 'prop-types';

class Greeting extends React.Component {

static propTypes = {
name: PropTypes.string.isRequired//必传且是String类型
}

  render() {
    return (
      <h1>Hello, {this.props.name}</h1>
    );
  }
}


或者

Greeting.propTypes = {
  name: PropTypes.string.isRequired//必传且是String类型
};

3.2、默认属性

可以通过defaultProps用来设置组件属性的默认值。      

class MyTitle extends React.Component{
static defaultProps = {
    shortName:'MyTitle'
   };

render(){
    return (<h1>{this.props.shortName}</h1>);
  }

}

ReactDOM.render(<MyTitle/>,document.getElementById('root'));

3.3、ref属性

组件并不是真实的DOM节点,而是存在于内存之中的一种数据结构,叫做虚拟DOM。只有当它插入文档以后,才会变成真实的DOM。根据React的设计,所有的DOM变动,都先在虚拟DOM上发生,然后再将实际发生变动的部分,反应在真实DOM上,这种算法叫做DOM diff,它可以极大提高网页的性能表现。

有时,需要从组件获取真实DOM的节点,这是就要用到ref属性。

class Alert extends React.Component {

  showAlert() {
    alert('alert');
  }

  render() {
    return null;
  }

}

class MyTitle extends React.Component {

  onClick = () => {
    this.refs.alert.showAlert();
  };

  render() {
    <div>
      <h1 onClick={this.onClick}>click me</h1>
      <Alert ref='alert' />
    </div>
  }
}

需要注意的是,由于this.refs.[refName]属性获取的是真实的DOM,所以必须等到虚拟DOM插入文档以后,才能使用这个属性,否则会报错。上面的代码,通过组件指定click事件的回调函数,确保了只有等到真实DOM发生Click事件之后,才会读取this.refs.[refName]属性。

3.4、组件的生命周期

注意:下述方法即将过时,在新代码中应该避免使用它们


图一:比较常用的生命周期图

 

图二:完整的生命周期图

注:强烈建议你不要创建自己的组件基类。在React组件中,代码重用的主要方式是组合而不是继承。具体生命周期的详细说明:参阅官档。

3.5、render方法

render方法是必须的。当被调用时,其会检查this.props和this.state并返回以下类型中的一个:

  • react元素:通常是由JSX创建。该元素可能是一个原生DOM组件的表示,如<div/>或者是一个你定义的复合组件。
  • 字符串和数字:这些将被渲染为DOM中的text node。
  • Portals:由ReactDOM.createPotral创建。
  • null:什么也不渲染;
  • 布尔值:什么也不渲染。(通常存在于return test && 写法,其中test是布尔值)

返回null或者false时,ReactDOM.findDOMNode(this)将返回null。

render()函数应该是纯粹的,也就是说该函数不修改组件的state,每次调用都返回相同的结果,不读写DOM信息,也不和浏览器交互(例如通过使用setTimeOut)。如果需要和浏览器交互,在componentDidMount中或者其他生命周期方法中做这件事情。保持render()纯粹,可以使服务器渲染更加切实可行,也使组件更容易被理解。

注:若shouldComponentUpdate返回false,render函数将不会被调用。

4、React Native组件的生命周期

4.1、布局基础

1)父视图属性

  • flexDirection: enum('row', 'column ', 'row-reverse', 'column-reverse') - 默认column
  • flexWrap:enum('wrap','nowrap') - 是否换行
  • justContent:enum(‘flex-start’, 'flex-end', 'center', 'space-between', 'space-around') - 主轴(x轴)上子元素排列方式
  • alignItems:enum('flex-start', 'flex-end', 'center', 'stretch') - 次轴(y轴)上,子元素的排列。stretch,弹性元素被在侧轴方向被拉伸到与容器相同的高度或者宽度。

2)子视图属性

  • alignSelf:定义了flex容器内被选中项目的对齐方式。注意:alignSelf属性可重写灵活容器的alignItems属性。
  • flex

3)其他属性

  • borderWidth、borderColor、borderRadius等
  • 定位:

    a)absolute:

生成绝对定位的元素,元素的位置通过'left'、'top'、'right'、'bottom'属性进行规定。

    b)relative(默认):

生成相对定位的元素,相对于其正常位置进行定位。因此,left:20会向元素的left增加20像素。

5、react-navigation

最权威的学习文档 - 官方文档 - https://reactnavigation.org/docs/zh-Hans/getting-started.html

提供“页面跳转(stackNavigator)”、“顶部Tab(可滚动)”、“底部Tab”、“侧滑抽屉效果”等功能。

以createStackNavigator为例(其余的):

  • RouteConfigs(必选):路由配置对象是从路由名称到路由配置的映射,告诉导航器该路由呈现什么。
RouteConfigs支持三个参数screen、path以及navigationOptions;

screen(必选):指定一个 React 组件作为屏幕的主要显示内容,当这个组件被createStackNavigator加载时,它会被分配一个navigation prop。

path(可选):用来设置支持schema跳转时使用;

navigationOptions(可选):用以配置全局的屏幕导航选项如:title、headerRight、headerLeft等;
  • StackNavigatorConfig(可选):配置导航器的路由(如:默认首屏,navigationOptions,paths等)样式(如,转场模式mode、头部模式等)。
从react-navigation源码中可以看出StackNavigatorConfig支持配置的参数有10个。

function createStackNavigator(routeConfigMap, stackConfig = {}) {
  const {
    initialRouteKey,
    initialRouteName,
    initialRouteParams,
    paths,
    navigationOptions,
    disableKeyboardHandling,
    getCustomActionCreators
  } = stackConfig;
  ...

routeConfig的screen既可以是一个Page,也可以是一个Navigator。比如:

export const AppStackNavigator = createStackNavigator({
    HomePage: {
        screen: HomePage
    },
    Page1: {// 动态配置
        screen: Page1,
        navigationOptions: ({ navigation }) => ({
            title: navigation.state.params.name + '页面名'
        })
    },
    Page2: {
        screen: Page2,
        navigationOptions: {//静态配置
            title: 'this is page2'
        }
    },
    Page3: {
        screen: Page3,
        navigationOptions: (props) => {
            const { navigation } = props
            const { state, setParams } = navigation
            const { params } = state
            return ({
                title: params.title ? params.title : 'this is page3',
                headerRight: (<Button
                    title={params.mode === 'edit' ? '编辑' : '保存'}
                    onPress={() => setParams({ mode: params.mode === 'edit' ? '' : 'edit' })
                    }
                />)
            });
        }
    },
    Bottom: {
        screen: AppBottomNavigator,
        navigationOptions: {
            title: '底部'
        }
    },
    Top: {
        screen: AppTopTabNavigator,
        navigationOptions: {
            title: '顶部'
        }
    }
});
-----------------------------------------------------------------
import { createAppContainer } from 'react-navigation'
import { AppStackNavigator } from './navigators/AppNavigator'

AppRegistry.registerComponent(appName, () => createAppContainer(AppStackNavigator));

一个不错的react-native 矢量图标库:https://oblador.github.io/react-native-vector-icons/

一个不错的入门博文:http://www.devio.org/2018/05/15/navigator-to-react-navigation/

关于react-navigation必须知道的一点:

a)当导航器中的配置的页面被打开时,它的props会收到一个navigation属性navigation属性是整个导航环节的关键一员。

navigation包含一下功能:

  • navigate:跳转到其他界面;
  • state:屏幕的当前state;
  • setParams:改变路由的params;
  • goBack:关闭当前屏幕;
  • dispatch:向路由发送一个action;

可以通过this.props.state.params来获取通过setParams(),或navigation.navigate()传递的参数。

<Button
    title={params.mode === 'edit' ? '保存' : '编辑'}
    onPress={() =>
        setParams({mode: params.mode === 'edit' ? '' : 'edit'})}
/>
<Button
    title="Go To Page1"
    onPress={() => {
        navigation.navigate('Page1',{ name: 'Devio' });
    }}
/>
const {navigation} = this.props;
const {state, setParams} = navigation;
const {params} = state;
const showText = params.mode === 'edit' ? '正在编辑' : '编辑完成';

注意:navigation.setParams改变的是当前页面的Params,如果要改变其他页面的Params可以通过NavigationActions.setParams完成。

注意:一个navigation有可能没有navigate、setParams以及goBack,只有state与dispatch,所以在使用navigate时要进行判断,如果没有navigate可以使用navigation去dispatch一个新的action。

  • SafeAreaView可以适配全面屏 - 仅支持iOS;

6、列表相关

FlatList与SectionList的底层实现都是VirtualizedList,因此类似于Android中的RecyclerView,存在Item的复用机制,是一个高性能的列表渲染组件。老版本的ListView由于没有这种复用机制,性能相对较差,基本废弃使用。

VirtualizedList - 支持滚动加载(onEndReached)、下拉刷新(onRefresh/refreshing)、可见性配置(onViewableItemsChanged/viewabilityConfig实现)、滑动方向、更智能的Item及section separators支持、Multi-column(借助numColumn)、对Flow更加友好、添加scrollToEnd、scrollToIndex和scrollToItem方法的支持;

FlatList - 高性能的列表组件;SectionList - 支持头部分组的列表组件;SwipeableList - 支持侧滑操作的列表组件;

未完待续.......

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值