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
方法
實例化:getInitialState
,componentWillMount
,render
(渲染并返回一個虛擬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()方法。有幾個點需要注意:
- 一切界面變化都是狀態state變化
- state的修改必須通過setState()方法
- setState 是一個 merge 合并操作,只修改指定屬性,不影響其他屬性
- 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 對象,還可以傳入一個數組——在數組中位置居后的樣式對象比居前的優先級更高,這樣可以間接實現樣式的繼承。
定義樣式
- HTML5以 ‘;’ 結尾
RN 以 ‘,’ 結尾- HTML5的key、value都不加引號
RN中屬于js對象,key的名字不能出現‘-’,要使用駝峰命名法;如果value為字符串,需要加引號- 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來實現網絡請求的??梢詤⒖?a target="_blank">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.支持上拉加載。