前段時(shí)間參加了一場知乎Live萝勤,老師解析得很透徹,昨天仔細(xì)又聽了幾遍,寫個(gè)筆記分享出來:
理解React的工作原理
本質(zhì):
-
UI = f(data)
- 數(shù)據(jù)(props & state)驅(qū)動(dòng)function改變UI
- 如何實(shí)現(xiàn),對(duì)大部分dev來說不care,virtual Dom澎办, DIff函數(shù)
- virtual Dom如何比對(duì):
- 動(dòng)態(tài)使用子組件的時(shí)候一定要使用key
- diff算法:用來比對(duì)文件前后的變化(類似git diff,git diff的算法時(shí)間復(fù)雜度O(n^3))
- react放棄比對(duì)(如下圖:A移動(dòng)到B),取其次:刪除A金砍,R上增加X,B上增加A(O(n)的時(shí)間復(fù)雜度局蚀,從根節(jié)點(diǎn)往下比對(duì),先比較類型恕稠,類型不同琅绅,會(huì)觸發(fā)Mount,類型相同會(huì)觸發(fā)update)
- image
-
key的作用:由于react使用了另一種比對(duì)方式鹅巍,當(dāng)遇到如下場景千扶,會(huì)產(chǎn)生很多不必要的渲染消耗,動(dòng)態(tài)產(chǎn)生的子組件需要key這個(gè)prop:image
- 1.key的值在兄弟節(jié)點(diǎn)之間唯一骆捧,2.key的值在渲染的過程中要穩(wěn)定
一切都是組件
組件化:軟件都像樂高積木一樣
組件化的模型不需要關(guān)心別人的積木怎么搭
react中組件可以做任何事情聲明式編程 (Declarative Programming)
實(shí)現(xiàn)了申明式:很少去調(diào)用react的api澎羞,聲明式,而不是主動(dòng)去調(diào)用API改變
冒泡:拍桌子-》拍大樓-》拍地球
jq敛苇,命名式設(shè)計(jì)妆绞,對(duì)冒泡的處理:bind(), live(), delegate(),on()
JSX的優(yōu)勢(shì)與局限
爭議:HTML內(nèi)容,CSS樣式枫攀,JS動(dòng)態(tài)括饶。全都放到一個(gè)文件里
結(jié)論:應(yīng)該遵循相關(guān)邏輯code應(yīng)該放到一起的原則
CSS侵入性:引入一個(gè)class影響全局css class
麻煩:jsx需要babel,又需要webpack
render函數(shù):
1.花括號(hào)里不能寫語句,只能寫表達(dá)式
2.純函數(shù)来涨,不要使用push图焰,reverse。蹦掐。
使用props還是state
react一切皆組件技羔,小組件組成大組件
props:組件外部傳入的數(shù)據(jù)
state:組件內(nèi)部的狀態(tài)僵闯,一個(gè)組件的state可以作為
傳給子組件的數(shù)據(jù)來源,一個(gè)組件改變自己的狀態(tài)只能改變state藤滥,絕對(duì)不能修改傳入的props
盡量構(gòu)建一個(gè)state很少的組件(無狀態(tài))盡量使用props解決問題
生命周期
三種過程:
- mount:從無到有
- update: 因?yàn)闋顟B(tài)改變或者屬性改變鳖粟,分為state
change引發(fā)的,和props引發(fā)的 - unmount:從有到無的過程
mount過程:
getDefaultProps(默認(rèn)props)
getInitialState(初始的state)
componentWillMount(mount之前做的事情)
render(執(zhí)行這個(gè)改變state與props)
componentDidMount(只在瀏覽器端執(zhí)行超陆,服務(wù)器端吐出來的是字符串)
因state改變引發(fā)的update過程:
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
因父組件想要render這個(gè)組件改變引發(fā)的update過程:
componentWillReceiveProps
shouldComponentUpdate(可以截胡牺弹,節(jié)省不必要的渲染性能開銷浦马,提高react性能)
componentWillUpdate
render
componentDidUpdate
為什么盡量使用無狀態(tài)組件
組件分解时呀,遵守函數(shù)式編程的原則,大部分組件以純函數(shù)形式表現(xiàn)(單元測試晶默,少bug)
組件分類為:有狀態(tài)+無狀態(tài)有些寬泛谨娜,也可以有組件什么都不畫
import React from 'react';
export default class HeartBeat extends React.Component {
render() {
return null;
}
componentDidMount() {
this.timer = setInterval(() => {
fetch('/api/v1/heartbeat');
}, 5000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
}
創(chuàng)建高階組件(HoC,Higher-Order Component)
HOC應(yīng)用場景:如果功能在組件之間可以共享磺陡,那么創(chuàng)建HOC
包含方式創(chuàng)建:
const HoC = (WrappedComponent) => {
const WrappingComponent = (props) => (
<div className="foo">
<WrappedCompoent {...props} />
</div>
);
return WrappingComponent;
};
繼承方式創(chuàng)建(不推薦):
const HoC = (WrappedComponent) => {
class WrappingComponent extends WrappendComponent {
render() (
const {user, ...otherProps} = this.props;
this.props = otherProps;
return super.render();
}
}
return WrappingComponent;
};
一個(gè)HOC沒有說只有一個(gè)組件類作為參數(shù):
const HoC = (WrappedComponent, LoginView) => {
const WrappingComponent = () => {
const {user} = this.props;
if (user) {
return <WrappedComponent {...this.props} />
} else {
return <LoginView {...this.props} />
}
};
return WrappingComponent;
};
組件之間通訊
對(duì)react來說趴梢,組件間通信的確是一件棘手的事情,所以在構(gòu)建大型應(yīng)用的時(shí)候币他,我們不得不引入第三方的東西來處理(比如:redux)
- 父子通信關(guān)系
方法一:- 父傳子:props直接傳
- 子傳父:父通過props傳遞函數(shù)讓子調(diào)用來影響父
方法二: - ref(不推薦)
-
callback(promise)
父子通信
-
兄弟通信關(guān)系
父組件造兩個(gè)函數(shù)傳給兩個(gè)子組件坞靶,父組件橋接作用,讓兩個(gè)子組件通信(很笨拙)
兄弟通信 -
任意位置兩個(gè)組件通信
全局變量+emmit
任意位置組件通信