React是一個用于構(gòu)建用戶界面的JavaScript庫
一、基礎知識學習
1. JSX
const element = <h1>hello world<h1>
JSX是一個JavaScript的語法擴展遵循xml和html語法层宫。
可以在JSX中使用表達式:
const name = 'lucy';
const element = <h1>hello {name}</h1>;
ReactDOM.render(
element,
document.getElementById("root")
)
JSX也是一個表達式
可以在if語句和for循環(huán)語句的代碼塊中使用JSX,將JSX賦值給變量洞翩,把JSX當做參數(shù)傳入馁启,以及從函數(shù)中返回JSX
var name = "lucy"
function greeting(name){
if(name){
return <h1>Hello, {name}</h1>
}
return <h1>Hello Stranger</h1>
}
JSX特定屬性
const element = <div name="lucy"></div>
const element = <img src={user.avatar}></img>
注意:JSX語法上更接近JS蒋院,所以React DOM使用小駝峰(cameCase)命名來定義屬性的名稱厢绝,而不使用HTML屬性名稱的命名約定买决。
例如沛婴,JSX中class變成了ClassName,onclick變成了onClick.
2. 組件
類似于JS函數(shù),接受任意入?yún)ⅲ╬rops),并返回用于描述頁面展示內(nèi)容的React元素督赤。
函數(shù)組件
function Welcome(props){
return <h1>Hello {props.name}</h1>
}
class組件
class Welecome extends React.Component{
render(){
return <h1>Hello,{this.props.name}</h1>
}
}
這兩個組件在React里是等效的嘁灯。
注意:組件名稱必須大寫字母開頭(React會將小寫字母開頭組件視為原生DOM標簽)
3. Props
純函數(shù):函數(shù)不會更改入?yún)ⅲ叶啻握{(diào)用下相同的入?yún)⑹冀K返回相同的結(jié)果躲舌。
function sum(a,b){
return a+b
}
組件無論如何都不能修改自身props丑婿,所有的組件都必須像純函數(shù)一樣保護它們的props不被修改。
定義與使用:
function Welcome (props){
return <h1>{props.name}</h1>
}
ReactDOM.render(
<Welcome name="jack"/>,
document.getElementById("root")
)
4. State
State與props類似,但是state是私有的羹奉,并且完全受控于當前組件秒旋,可以將當前組件state當做子組件的props傳遞。
定義與使用:
class Welcome extends React.Component{
constructor(props){
super(props);
this.state = {
name:"lucy"
}
}
render(){
return(
<div>
<h1>welcome!!!</h1>
<h1>{this.state.name}</h1>
</div>
)
}
}
ReactDOM.render(
<Welcome/>,
document.getElementById("root")
)
5. setState
React規(guī)定不要直接修改State
因此需要使用setState()
方法實現(xiàn)修改state
例如尘奏,此代碼不會重新渲染組件
//假如組建中state為 this.state = {name : "jack"}
this.state.name = "lucy"
而使用setState就可以
this.setState({
name:"lisa"
})
構(gòu)造函數(shù)是唯一可以給this.state賦值的地方滩褥。
State的更新可能是是異步的。
因為this.props和this.state可能會異步更新炫加,所以不要依賴他們的值瑰煎。
//wrong
this.setState({
name:this.state.firstName + this.props.lastName,
})
解決:讓setState()接收一個函數(shù)而不是一個對象,這個函數(shù)用上一個state作為第一個參數(shù)俗孝,將此次更新被應用時的props作為第二個參數(shù):
//correct
this.setState((state,props)=>{
name:state.firstName + props.lastName
});
setState方式是異步的:
//...假設組件的state = {name:"lisa"},組件上有個按鈕點擊執(zhí)行handleClick事件
handleClick(){
this.setState({
name:"lucy"
},()=>{
console.log("setState()執(zhí)行完畢")
})
console.log('setState()執(zhí)行之前')
}
setState()方法接收第二個參數(shù)酒甸,類似于一個回調(diào)函數(shù),當數(shù)據(jù)更新之后才會執(zhí)行回調(diào)里面的方法赋铝,上述代碼輸出順序為“setState()執(zhí)行之前”=>“setState()執(zhí)行完畢”插勤。
關(guān)于setState可以參考這篇文章:你真的理解setState嗎?
6. 生命周期
組件生命周期三個階段
- Mounting(加載階段)
- Updating(更新階段)
-
Unmounting(卸載階段)
react生命周期
Mounting階段執(zhí)行鉤子函數(shù):
- constructor
- getDefaultProps
- getInitialState
- componentWillMount
- render
- componentDidMount
Updating階段執(zhí)行鉤子函數(shù):
當props發(fā)生改變
- compoentWillReceProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
當state發(fā)生改變
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
Unmounting階段執(zhí)行鉤子函數(shù):
- componentWillMount
7. 事件處理
- React事件的命名采用小駝峰式(camelCase)革骨,而不是純小寫农尖。
- 使用JSX語法時需要傳入一個函數(shù)作為事件處理函數(shù),而不是一個字符串良哲。
事件處理函數(shù)中的this
:
class Toggle extends React.Component {
constructor(props){
super(props)
this.state = {isToggle:true};
}
handleClick(){
this.setState((state)=>({
isToggle:!state.isToggle
}));
}
render(){
return (
<button onClick={this.handleClick}>
{this.state.isToggle ? "ON" : "OFF"}
</button>
)
}
ReactDOM.render(
<Toggle />,
document.getElementById("root")
)
}
此時handleClick
中的this
指向為undefined
盛卡,因為this.handleClick傳給了button組件后是丟失了this的!如下:
var obj = {
f : function(){
console.log(this)
}
}
function foo(f){
f()
}
foo(obj.f)
個人覺得這個例子很形象筑凫,foo運行時接收到的參數(shù) f 時滑沧,foo是并不知道 f 是obj的屬性,也就是常說的丟失了上下文巍实。
關(guān)于React中this指向問題可以參考知乎文章https://www.zhihu.com/question/68092028?sort=created
this指向更正比較主流的有三種滓技,第一種是在調(diào)用時綁定:
render(){
return (
<button onClick={this.handleClick.bind(this)}>
{this.state.isToggle ? "ON" : "OFF"}
</button>
)
}
第二種是在constructor中綁定:
constructor(){
this.handleClick = this.handleClick.bind(this);
}
render(){
<button onClick={this.handleClick}>
{this.state.isToggle ? "ON" : "OFF"}
</button>
}
第三種是使用public class fields
語法:
handleClick = ()=>{
console.log(this)
}
render(){
return (
<button onClick = {this.handleClick}>
Click me
</button>
)
}
還有一種是在調(diào)用的時候直接用一個箭頭函數(shù)包起來:
render(){
return (
<button onClick = {()=>{this.handleClick()}}>
Click me
</button>
)
}
響事件處理程序中傳遞參數(shù):
handleClick(id,e){
e.preventDefault();
}
<button onClick = {(e)=>{this.handleClick(id,e)}}>Delete</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete</button>
這兩種情況下,React的事件對象e會被作為第二個參數(shù)傳遞棚潦,如果通過箭頭函數(shù)的方式令漂,事件對象必須顯式的進行傳遞,而通過bind的方式瓦盛,事件對象以及更多的參數(shù)將會被隱式的進行傳遞洗显。
8. 組件通信
父子通信:通過props數(shù)據(jù)由父組件流向子組件
// Father.js
import React , {Component} from 'react';
import Child from './Child';
export default class Father extends Component {
constructor(){
super()
this.state = {
name:"father",
age:20
}
}
render(){
return(
<div>
{this.state.name}
<div><Child faname={this.state.name}/></div>
</div>
)
}
}
//Child.js
import React ,{ Component } from 'react'
export default class Child extends Component{
constructor(){
super()
this.state = {
name:"Child",
age:10
}
}
render(){
return (
<div>{this.state.name}</div>
)
}
componentWillMount(){
this.setState({
name:this.props.faname
})
}
}
父組件中的state通過給子組件傳遞屬性的方式傳遞給子組件,子組件可以通過this.props.屬性名
獲取到原环。
子父通信:通過方法通信(可以理解為回調(diào)函數(shù)通信)挠唆,在子組件中觸發(fā)一個通過props接收的從父組件傳遞過來的事件,并把子組件的state通過參數(shù)傳遞給事件嘱吗,這樣在父組件的方法中就能獲通過參數(shù)獲取子組件中的state
//Father.js
import React , {Component} from 'react';
import Child from './Child';
export default class Father extends Component {
constructor(){
super()
this.state = {
name:"father",
age:20
}
}
render(){
return(
<div>
{this.state.name}
<div><Child toChildEvent = {this.getChildState.bind(this)}/></div>
</div>
)
}
getChildState(childName){
this.setState({
name:childName
})
}
}
//Child.js
import React ,{ Component } from 'react'
export default class Child extends Component{
constructor(){
super()
this.state = {
name:"Child",
age:10
}
}
render(){
return (
<div>{this.state.name}</div>
)
}
componentWillMount(){
this.props.toChildEvent(this.state.name);
}
}
首先在父組件中定義一個方法玄组,叫做getChildState
滔驾,然后通過屬性綁定給<Child/>
組件,屬性名為toChildEvent
(自定義)俄讹,之后在子組件中通過props
接收到該toChildEvent
屬性哆致,也就是getChildState
方法,然后在componentWillMount
生命周期鉤子函數(shù)中執(zhí)行患膛,并傳入?yún)?shù)摊阀,然后就在父組件中getChildState
方法可以通過參數(shù)獲得子組件中state
。
兄弟通信:采用狀態(tài)提升方案踪蹬,將兄弟間需要共享的數(shù)據(jù)胞此,通過子父方法通信傳遞給最近共同父組件,之后通過父組件再通過props將數(shù)據(jù)流向各子組件
可以參考官網(wǎng)狀態(tài)提升
待續(xù)跃捣。漱牵。。疚漆。酣胀。。