React Native基础入门

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.支持上拉加载。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容