學(xué)完JavaScript后,就可以進下一步,學(xué)習(xí)React的開發(fā)了,學(xué)習(xí)Reac需要掌握幾個知識點,JSX語法、組件、狀態(tài),生命周期。
React語法基礎(chǔ)
關(guān)于React的語法,可以參考React 入門實例教程,基本可以對幾個基礎(chǔ)語法點進行理解,不過文章面對的是React.js,具體語法有一點點區(qū)別。下面的案例,基本語法點保持一致,但是面對的是ReactNative。
編寫的時候,如果想方便,也可以在在線模擬器上進行練習(xí)。
顯示一個組件
// demo1.js
// 導(dǎo)入依賴包
import React, { Component } from 'react'
import {
AppRegistry,
Text,
View,
} from 'react-native'
// 定義一個組件
export default class App extends Component{
render() {
return (
<View>
<Text>Hello World!</Text>
</View>
)
}
}
// JS運行所有React Native應(yīng)用的入口。應(yīng)用的根組件應(yīng)當(dāng)通過AppRegistry.registerComponent方法注冊自己,然后原生系統(tǒng)才可以加載應(yīng)用的代碼包
AppRegistry.registerComponent('App', () => App)
JSX語法
通過JSX語法,可以使得HTML和JavaScript語法混寫,如果想寫HTML語法,就使用<>,如果使用JavaScript語法,則使用{}。
JSX不是一種標(biāo)記語言,實質(zhì)是調(diào)用React.createElement函數(shù),所以在開發(fā)中使用其時,要在頭部定義import React from 'react';。
// demo2.js
export default class App extends Component{
render() {
let name = "yuan"
return (
<View>
<Text>Hello {name}!</Text>
</View>
)
}
}
語法規(guī)則
標(biāo)簽首字母必須大寫
-
開始和結(jié)束標(biāo)簽配對
<組件>內(nèi)容</組件> // 如果無內(nèi)容的組件,標(biāo)簽應(yīng)寫成自封閉形式 <組件/> -
必須為單一子節(jié)點,如果有多個節(jié)點,最外層可以用
<View></View>嵌套起來// 錯誤做法 return ( <View> <Text>Hello World!</Text> </View> <View> <Text>Hello World!</Text> </View> ) // 正確做法 return ( <View> <View> <Text>Hello World!</Text> </View> <View> <Text>Hello World!</Text> </View> </View> )
注釋
在JSX代碼內(nèi),注釋只能使用{/* 注釋內(nèi)容 */}
// demo3.js
export default class App extends Component{
render() {
let name = "yuan"
// JSX外的注釋
return (
<View>
{/*JSX的注釋*/}
<Text>Hello {name}!</Text>
</View>
)
}
}
組件
在React Native開發(fā)中,一個個布局可以通過創(chuàng)建組件的方式搭建起來,然后通過return返回一個在頁面上展示的React元素。定義一個組件有兩種方式,一種是通過function,稱為函數(shù)定義組件,功能比較簡單的組件可以采用該方法。另外一種是通過繼承class,稱為類定義組件??梢园呀M件類似認為,在Android開發(fā)中,在java類中創(chuàng)建自定義View,然后把View添加到原有布局中。
// demo4.js
// 函數(shù)定義組件,采用箭頭函數(shù)
const HelloWorld = () => {
return (
<Text>Hello world!</Text>
);
}
// 類定義組件,與上面的效果一致
class HelloWorld extends Component{
render() {
return (
<Text>Hello World!</Text>
)
}
}
組件屬性props
每次在使用的時候,不可能組件內(nèi)容都一樣,所以,需要可以在使用的時候,傳入不同的值,改變組件里面的內(nèi)容,那么就可以使用關(guān)鍵字props。
// demo5.js
// 函數(shù)定義組件,屬性需要傳遞進去
const HelloWorld = (props) => {
return (
<Text>Hello {props.name}!</Text>
);
}
// 類定義組件,屬性通過this.props獲取,與上面的效果一致
class HelloWorld extends Component{
render() {
return (
<Text>Hello {this.props.name}!</Text>
)
}
}
class App extends Component{
render() {
return (
<View>
<HelloWorld name="yuan"/>
</View>
)
};
}
自定義屬性,字符串應(yīng)使用雙引號,其他值用{}括起來,布爾值可省略,默認為true。
<Person age={30} sex="male" married/>
類定義組件屬性
class HelloWorld extends Component{
// 如果組件沒有設(shè)置該屬性,則會使用默認值
static defaultProps = {
name:"yuan",
};
// 約定組件屬性所需要的類型(為字符串),如果類型不符合,編譯的時候會報錯
static propTypes = {
name: React.PropTypes.string,
};
render() {
return (
<Text>Hello {this.props.name}!</Text>
)
}
}
變量作用域
- 函數(shù)內(nèi)的局部變量,只能函數(shù)內(nèi)讀寫,函數(shù)運行完后銷毀(閉包除外)
-
class內(nèi)的成員變量,在單個class的實例內(nèi)讀寫,實例銷毀時一并銷毀
- 使用時不要忘記this.
-
class內(nèi)的靜態(tài)成員變量,在所有class的實例內(nèi)共享,不會自動銷毀
- 其他模塊可通過此class訪問(類public
-
class外的變量,在所有class的實例內(nèi)共享(公有),不會自動銷毀
- 除非明確export,否則其他模塊不可訪問(類private)
狀態(tài)state
上面講到了不同的屬性值,可以用props,但是其值一經(jīng)指定,在組件的生命周期中則不再改變。 對于需要改變的數(shù)據(jù),我們就需要使用state。
// demo6.js
// 定義一個文字按鈕的組件
class LikeButton extends Component{
// 設(shè)置默認狀態(tài)值為false,同時也聲明為boolean類型
state = {
liked : false
};
// 定義一個函數(shù),響應(yīng)點擊事件,改變state的值,方法名可以任意
onPress = () => {
this.setState({
liked: !this.state.liked
})
};
render() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<View>
{/*聲明了點擊事件執(zhí)行的方法*/}
<Text onPress={this.onPress}>
You {text} this. Click to toggle.
</Text>
</View>
)
};
}
export default class App extends Component{
render() {
return (
<View>
<LikeButton/>
</View>
)
}
}
state的變化,必須通過setState()方法,不能直接賦值修改
-
setState是異常操作,修改不會馬上生效
onPress = () => { console.log(this.state.liked) this.setState({ liked: !this.state.liked }); console.log(this.state.liked) }; // 結(jié)果的輸出,兩次都保持一樣,執(zhí)行setState()后,該值不會立馬生效,還是保持原來的狀態(tài)值 setState被執(zhí)行后,會觸發(fā)render,對界面重新渲染,所以,不要再renser,對數(shù)據(jù)進行改變,避免會調(diào)用到setState,導(dǎo)致死循環(huán)。
組件的生命周期
組件的生命周期,可以分為三個狀態(tài):
- Mounting:已插入真實 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真實 DOM
React 為每個狀態(tài)都提供了兩種處理函數(shù),will 函數(shù)在進入狀態(tài)之前調(diào)用,did 函數(shù)在進入狀態(tài)之后調(diào)用,三種狀態(tài)共計五種處理函數(shù):
- componentWillMount()
- componentDidMount()
- componentWillUpdate(object nextProps, object nextState)
- componentDidUpdate(object prevProps, object prevState)
- componentWillUnmount()
此外,React 還提供兩種特殊狀態(tài)的處理函數(shù):
- componentWillReceiveProps(object nextProps):已加載組件收到新的參數(shù)時調(diào)用
- shouldComponentUpdate(object nextProps, object nextState):組件判斷是否重新渲染時調(diào)用
各種組件處理函數(shù)的流程圖如下
實例代碼
// dmeo7.js
class TextOpacity extends Component{
state = {
opacity : 1.0
};
componentDidMount() {
this.timer = setInterval(() => {
let opacity = this.state.opacity;
opacity -= 0.05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity
});
},100);
}
// 卸載后清空時鐘
comnponentWillUnmount() {
clearInterval(this.timer)
}
render() {
return (
<Text style={{opacity:this.state.opacity}}>
Hello world
</Text>
)
}
}
export default class App extends Component{
render() {
return (
<View>
<TextOpacity/>
</View>
)
}
}
上面代碼在TextOpacity組件加載以后,默認設(shè)置透明度為1,然后通過 componentDidMount 方法設(shè)置一個定時器,每隔100毫秒,就重新通過setState設(shè)置組件的透明度,從而引發(fā)重新渲染調(diào)用render。
參考資料
