纵横研究院React技术专题社区

React Native基础入门

2019-06-04  本文已影响8人  Lethe35

1.React Native组件

独立的、可重用的模块。
有3种方式可以创建组件:1. ES6方式创建;2. ES5方式创建;3.函数式定义无状态组件方式

// ES6方式创建组件
type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Welcome to React Native!</Text>
        <Text style={styles.instructions}>To get started, edit App.js</Text>
        <Text style={styles.instructions}>{instructions}</Text>
      </View>
    );
  }
}

// ES5方式创建组件
var App = React.createClass({
  render(){
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Welcome to React Native!</Text>
        <Text style={styles.instructions}>To get started, edit App.js</Text>
        <Text style={styles.instructions}>{instructions}</Text>
      </View>
    );
  }
})
module.exports = App;

// 无状态组件方式:没有this,没有生命周期函数
function App(){
  return (
    <View style={styles.container}>
      <Text style={styles.welcome}>Welcome to React Native!</Text>
      <Text style={styles.instructions}>To get started, edit App.js</Text>
      <Text style={styles.instructions}>{instructions}</Text>
    </View>
  );
}
module.exports = App;

2.React Native组件生命周期

React Native使用React语法,与React组件拥有一样的生命周期函数,

分为3种状态:
Mounting:挂载,已插入真实Dom
Updating:更新,正在被重新渲染
Unmounting:卸载,已移出真实Dom
4个阶段
创建:只调用getDefaultProps方法
实例化getInitialStatecomponentWillMountrender(渲染并返回一个虚拟Dom),componentDidMount(根据虚拟Dom对象创建真实Dom,可以在此获取Dom节点)
更新static getDerivedStateFromProps(props, state)shouldComponentUpdate(nextProps, nextState)render()getSnapshotBeforeUpdate(props, state)componentDidUpdate(preProps, preState, snapshot)
销毁componentWillUnmount

3.组件的导入与导出

// ES6:export导出,import导入
// 导出
export default class App extends Component{
  render() {
    return (
      <Text style={styles.welcome}>Welcome to React Native!</Text>
    );
  }
}
// 导入
import App from './App';

// ES5: module.export导出,import导入
// 导出
var App = React.createClass({
  render(){
    return (
      <Text style={styles.welcome}>Welcome to React Native!</Text>
    );
  }
})
module.exports = App;
//导入
import App from './App';

4.props

React相当于MVC的View层,负责展示,并不涉及到数据,但是组件在使用的过程中有两个属性是和数据有关的:props和state

props:组件自身的属性,一般用于嵌套的内外层组件中,由父组件传给子组件,负责传递信息,也可以用于属性约束和验证。(props对象中的属性与组件属性一一对应--除this.props.children之外,不要直接修改props属性中的值)
...this.props:可以将父组件中传递的全部属性复制给子组件
this.props.children:组件的所有子节点。它的返回值可以是任意类型的,所以用它来处理一些东西的时候很不方便,好在React的React.Children提供了处理this.props.children的一些方法:React.Children.map()React.Children.forEach()React.Children.count()React.Children.only()React.Children.toArray(),通常与React.cloneElement()结合使用来操作this.props.children。

属性验证:定义外部组件(父组件)传递的属性值类型是否符合组件定义的类型要求(一般在通用组件定义时使用)

propsTypes:在React15.5之前可以通过React.PropTypes 进行属性验证,之后我们需要借助prop-types库。

// 1.引入 prop-types 库
npm install --save prop-types

// 2.导入prop-types
import PropTypes from 'prop-types';

// 3.定义子组件
export default class  PropsTest extends Component{
    // 设置props的默认值
    static defaultProps={ name: 'xiao ming', age: 18, gender: 'man'}
    //约束的关键就是这里在定义属性的时候指定属性的类型,类似安卓private String name;
    static propTypes={
        name: PropTypes.string,
        age: PropTypes.number,
        gender: PropTypes.string.isRequired
    }
    render(){
        //在这里我们使用props中的name属性
          return (
            <Text>
              {this.props.name}+' age:'+{this.props.age}+'  gender:'+{this.props.gender}
            </Text>
          )
    }
}

// 4.定义父组件,并在父组件中调用子组件
export default class  HomePage extends Component{
    render(){
       const params = { name: 'daming', age: 20, gender: 'man' }
       return <PropsText {...params}/>
    }
}

5.state

我们使用两种数据来控制一个组件:props和state。props是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变。 对于需要改变的数据,我们需要使用state。state 的工作原理和 React.js 完全一致。
一般来说,你需要在 constructor 中初始化state(译注:这是 ES6 的写法,早期的很多 ES5 的例子使用的是 getInitialState 方法来初始化 state,这一做法会逐渐被淘汰),然后在需要修改时调用setState方法,每次调用setState都会重新调用组件render()方法。有几个点需要注意:

  1. 一切界面变化都是状态state变化
  2. state的修改必须通过setState()方法
  3. setState 是一个 merge 合并操作,只修改指定属性,不影响其他属性
  4. setState 是异步操作,修改不会马上生效,要获取到新设置的state属性,需要在setState的回调函数中
export default class  StateTest extends Component{
    // 设置state的默认值
   state = {
    name: '小红',
    age: 16,
    gender: 'women',
   };
   render(){
         return (
           <Text>
             {this.state.name}+' age:'+{this.state.age}+'  gender:'+{this.state.gender}
           </Text>
         )
   }
}

6.ref

父组件获取子组件的属性

// 子组件
export default class  RefTest extends Component{
    // 设置state的默认值
   state = { name: '小白' };
  getName(){
    return this.state.name;
  }
   render(){
         return (
           <Text>
             哈哈哈
           </Text>
         )
   }
}

// 父组件
import RefTest from './RefTest';
export default class  RefFather extends Component{
   render(){
         return (
            <View>
               <Text>
                  你好,{this.refTest.getName()}!
               </Text>
              <RefTest ref ={refTest => this.refTest=refTest} />
            </View>
         )
   }
}

7.样式

在 React Native 中,你并不需要学习什么特殊的语法来定义样式。我们仍然是使用 JavaScript 来写样式。所有的核心组件都接受名为style的属性。这些样式名基本上是遵循了 web 上的 CSS 的命名,只是按照 JS 的语法要求使用了驼峰命名法,例如将background-color改为backgroundColor。
style属性可以是一个普通的 JavaScript 对象,还可以传入一个数组——在数组中位置居后的样式对象比居前的优先级更高,这样可以间接实现样式的继承。

定义样式

  1. HTML5以 ‘;’ 结尾
    RN 以 ‘,’ 结尾
  2. HTML5的key、value都不加引号
    RN中属于js对象,key的名字不能出现‘-’,要使用驼峰命名法;如果value为字符串,需要加引号
  3. HTML5中,value如果是数字,需要加单位
    RN中,value是数字不需要加单位

实际开发中组件的样式会越来越复杂,建议使用StyleSheet.create来集中定义组件的样式。StyleSheet.create的参数是一个对象,对象中的每个属性都是以键值对的形式定义。

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
  android:
    'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

type Props = {};
export default class App extends Component<Props> {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.welcome}>Welcome to React Native!</Text>
        <Text style={styles.instructions}>To get started, edit App.js</Text>
        <Text style={styles.instructions}>{instructions}</Text>
      </View>
    );
  }
}

// StyleSheet.create方式定义样式
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});


// 通过style直接在组件内定义
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';

export default class FixedDimensionsBasics extends Component {
  render() {
    return (
      <View>
        <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
        <View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} />
        <View style={{width: 150, height: 150, backgroundColor: 'steelblue'}} />
      </View>
    );
  }
}

8.Flexbox布局

React Native 中使用 flexbox 规则来指定某个组件的子元素的布局。Flexbox 可以在不同屏幕尺寸上提供一致的布局结构。

1.宽高:组件的高度和宽度决定了其在屏幕上显示的尺寸,也就是大小
2.弹性(Flex)宽高:在组件样式中使用flex可以使其在可利用的空间中动态地扩张或收缩。一般而言我们会使用flex:1来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1,则这些子组件会平分父容器中剩余的空间(前提是其父容器的尺寸不为零,如果父容器既没有固定的width和height,也没有设定flex,则父容器的尺寸为零。其子组件如果使用了flex,也是无法显示的)。如果这些并列的子组件的flex值不一样,则谁的值更大,谁占据剩余空间的比例就更大(即占据剩余空间的比等于并列组件间flex值的比)
2.无单位:React Native 中的尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点,确保了在任何不同dpi的设备上显示都不会发生变化

React Native 中的 Flexbox 的工作原理和 web 上的 CSS 不同的是:

1.flexDirection:默认值是column,而不是row,而flex也只能指定一个数字值
2.alignItems:默认值是stretch,而不是flex-start
3.flex:只能指定一个参数并且是数字,而Web CSS中可以接受多参数
4.不支持属性:align-content,flex-basis,order,flex-flow,flex-grow,flex-shrink

9.网络请求

很多移动应用都需要从远程地址中获取数据或资源。你可能需要给某个 REST API 发起 POST 请求以提交用户数据,也可能只是需要从某个服务器上获取一些静态内容。
在React Native中是使用fetch来实现网络请求的。可以参考Fetch 请求文档来查看所有可用的参数。

发起请求
要从任意地址获取内容的话,只需简单地将网址作为参数传递给 fetch 方法即可

fetch('https://mywebsite.com/mydata.json');

Fetch 还有可选的第二个参数,可以用来定制 HTTP 请求一些参数,可以指定 header 参数,或是指定使用 POST 方法,或是提交数据等等:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  }),
});

提交数据的格式关键取决于 headers 中的Content-Type。Content-Type有很多种,对应 body 的格式也有区别。到底应该采用什么样的Content-Type取决于服务器端,所以请和服务器端的开发人员沟通确定清楚。常用的'Content-Type'除了上面的'application/json',还有传统的网页表单形式,如:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: 'key1=value1&key2=value2',
});

使用 Chrome 调试目前无法查看到 React Native 中的网络请求,可以使用第三方的react-native-debugger来进行查看。

10.基础组件

View
在Web开发中,div是最重要的一个元素,是页面布局的基础。在React Native开发中,View组件的作用类似于div,是最基本的组件,被看作是容器组件,不管是显示一个文本还是输入框,都可以把它们放在View组件内部。不论在什么平台上,View 都会直接对应一个平台的原生视图,无论它是 UIView、div还是 android.view.View

Text
显示文本内容的组件

Image
显示图片内容的组件。用于显示多种不同类型图片的 React 组件,包括网络图片、静态资源、临时的本地图片、以及本地磁盘上的图片(如相册)等

TextInput
文本输入框组件

ScrollView
可滚动的容器视图。封装了平台的ScrollView(滚动视图)的组件,同时还集成了触摸锁定的“响应者”系统。
必须要有一个确定的高度,在确保父级容器已经设置了高度情况下,可以通过设置flex: 1以使其自动填充父容器的空余空间

FlatList组件相比:ScrollView会简单粗暴地把所有子元素一次性全部渲染出来,毫无疑问这会导致一些性能问题,而FlatList会惰性渲染子元素,只在它们将要出现在屏幕中时才开始渲染。除非你要渲染的数据特别少,否则你都应该尽量使用FlatList,此外FlatList还可以方便地渲染行间分隔线,支持多列布局,无限滚动加载等等

StyleSheet
提供类似CSS样式表的样式抽象层

11.交互控件

常见的跨平台的交互控件
Button
一个简单的跨平台的按钮控件。组件的样式是固定的,可以使用TouchableOpacity或是TouchableNativeFeedback组件来定制自己所需要的按钮

Picker
在iOS和Android上调用各自原生的选择器控件。

<Picker
  selectedValue={this.state.language}
  style={{ height: 50, width: 100 }}
  onValueChange={(itemValue, itemIndex) => this.setState({language: itemValue})}>
  <Picker.Item label="Java" value="java" />
  <Picker.Item label="JavaScript" value="js" />
</Picker>

Slider
滑动数值选择器

Switch
开关,跨平台通用受控组件。通过onValueChange回调来更新value属性以响应用户的操作。如果不更新value属性,组件只会按一开始给定的value值来渲染且保持不变

12.列表视图

只会渲染当前屏幕可见的元素(懒加载),这样有利于显示大量的数据
FlatList
常用功能

1.完全跨平台。
2.支持水平布局模式。
3.行组件显示或隐藏时可配置回调事件。
4.支持单独的头部组件。
5.支持单独的尾部组件。
6.支持自定义行间分隔线。
7.支持下拉刷新。
8.支持上拉加载。
9.支持跳转到指定行(ScrollToIndex)

SectionList
类似FlatList,多了分组显示。
常用功能

1.完全跨平台。
2.行组件显示或隐藏时可配置回调事件。
3.支持单独的头部组件。
4.支持单独的尾部组件。
5.支持自定义行间分隔线。
6.支持分组的头部组件。
7.支持分组的分隔线。
8.支持多种数据源结构
9.支持下拉刷新。
10.支持上拉加载。

上一篇 下一篇

猜你喜欢

热点阅读