本文是我為最近一個(gè)月 React 學(xué)習(xí)和實(shí)踐的技術(shù)總結(jié),文章的前半部分主要是總結(jié) React 開發(fā)使用的技術(shù)棧和基礎(chǔ)知識(shí),在文章寫到后半部分,我深入地思考了 React 框架的特性,得出了 React 是一門融合了 函數(shù)式編程思想 的本質(zhì)上是 面向?qū)ο?的框架 這一結(jié)論.
語言:JSX(一種 JavaScript 的語法擴(kuò)展 JavaScript XML),Less(CSS 的語法擴(kuò)展),H5
IDE:VSCode
特點(diǎn):組件,元素
文件后綴: .jsx .less (并不需要.html)
vscode 插件:
?
技術(shù)棧
React提出了以組件化的形式重新構(gòu)建頁面內(nèi)容坝疼,所謂組件就是將頁面的內(nèi)容按特征分塊割卖,然后將特定塊中的HTML、CSS蛾派、JS封裝在一起,最后用組件來構(gòu)建頁面內(nèi)容。然而React不是一個(gè)完整的MVC,它只是V,也就是視圖表現(xiàn)勤众,采用React搭建完整的頁面還需要其它技術(shù)支持:npm、ES6鲤脏、JSX们颜、bable、less凑兰、Router掌桩、Redux、WebPack
NPM(node package manager)
通常稱為node包管理器姑食。顧名思義波岛,它的主要功能就是管理node包,包括:安裝音半、卸載则拷、更新、查看曹鸠、搜索煌茬、發(fā)布等。
npm的背后彻桃,是基于couchdb的一個(gè)數(shù)據(jù)庫坛善,詳細(xì)記錄了每個(gè)包的信息,包括作者邻眷、版本眠屎、依賴、授權(quán)信息等肆饶。它的一個(gè)很重要的作用就是:將開發(fā)者從繁瑣的包管理工作(版本改衩、依賴等)中解放出來,更加專注于功能的開發(fā)驯镊。
Node.js 就是運(yùn)行在服務(wù)端的 JavaScript葫督,是一個(gè)基于Chrome JavaScript 運(yùn)行時(shí)建立的一個(gè)平臺(tái),賦予了JavaScript很多面向?qū)ο笳Z言的特性
Node.js是一個(gè)事件驅(qū)動(dòng)I/O服務(wù)端JavaScript環(huán)境板惑,基于Google的V8引擎橄镜,V8引擎執(zhí)行Javascript的速度非常快冯乘,性能非常好蛉鹿。
ES6,bable
ES6即ECMAScript 2015,是 JavaScript 語言的下一代標(biāo)準(zhǔn)往湿,它和JavaScript的關(guān)系就是妖异,JS是ES的一種實(shí)現(xiàn)。
ES6中有很多新的特性领追,比如箭頭函數(shù)他膳、匹配賦值等,使的其更像是一門面向?qū)ο蟮恼Z言绒窑。
目前主流的瀏覽器還不支持ES6棕孙,所以需要通過轉(zhuǎn)碼器將ES6轉(zhuǎn)為ES5
bable就是目前主流的轉(zhuǎn)碼器,同時(shí)也將 JSX 解析,當(dāng)遇到“</>”,JSX就當(dāng)HTML解析些膨,遇到“{}”就當(dāng)JavaScript解析蟀俊。
Less (Leaner Style Sheets 的縮寫)
是一門向后兼容的 CSS 擴(kuò)展語言。他豐富了css選擇器的種類订雾,使程序員能夠在css中定義變量肢预,函數(shù),減少了css編寫的代碼量洼哎。同時(shí)他還支持選擇器之間的嵌套烫映,這樣css更有邏輯,更易維護(hù)噩峦,也更符合React組件化的思想锭沟,我們可以將一個(gè)React組件顯得選擇器封裝在一個(gè)嵌套層中,這樣邏輯更加清晰识补。
Router
傳統(tǒng)的web前端可以通過HTML文件的路徑來跳轉(zhuǎn)族淮,而React中都是組件,那么就不能通過傳統(tǒng)的方式來跳轉(zhuǎn)了凭涂,這時(shí)候Router就來了祝辣,他就是來解決這個(gè)問題的。
React Router 是一個(gè)基于 [React]之上的強(qiáng)大路由庫导盅,它可以讓你向應(yīng)用中快速地添加視圖和數(shù)據(jù)流较幌,同時(shí)保持頁面與 URL 間的同步。
Router還提供了<Link/>等組件方便使用
Ant design: UI 庫
文件結(jié)構(gòu):
src:項(xiàng)目結(jié)構(gòu)最主要的目錄
index.js:當(dāng)前目錄的入口文件
運(yùn)行 react 的命令:npm start
在編寫代碼之前:
import React from 'react'
import ReactDOM from 'react-dom'
其中白翻,react.js 是 React 的核心庫乍炉,react-dom.js 是提供與 DOM 相關(guān)的功能
JSX:
React 并不強(qiáng)制使用 JSX,但使用 JSX 會(huì)在視覺上有輔助作用
JSX 可以直接聲明一個(gè)元素為一個(gè)變量
const element = <h1>Hello, {name}</h1>;
JSX 可以在標(biāo)簽內(nèi)使用大括號(hào){}來嵌入一個(gè) JS 變量或表達(dá)式
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
JSX 可以在 if 語句和 for 循環(huán)的代碼塊中使用,也可作為參數(shù)和返回值來傳遞
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
JSX 中可以使用引號(hào)(單引號(hào)或雙引號(hào))來將屬性指定為字符串字面量
const element = <div tabIndex="0"></div>;
也可以使用大括號(hào),在屬性中插入一個(gè) JS 表達(dá)式
const element = <img src={user.avatarUrl}></img>;
JSX 可以使用 /> 來閉合標(biāo)簽
const element = <img src={user.avatarUrl} />;
JSX 標(biāo)簽里可以包含多個(gè)子元素
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);
JSX 語法本質(zhì)上是一個(gè)名為 React.createElement() 的函數(shù)
我們并不需要關(guān)心其本來面目是什么樣子的
基于babel/babel-loader: 把jsx語法編譯為react.create-Element這種模式
create-Element 至少有兩個(gè)參數(shù),沒有上限
第一個(gè): 標(biāo)簽名(字符串)
第二個(gè):屬性(沒有給元素設(shè)置null)
其他:當(dāng)前元素的所有子元素內(nèi)容
執(zhí)行create-Element 把傳遞的參數(shù)最后處理成為一個(gè)對(duì)象
元素渲染
使用 ReactDOM.render(元素名,根 DOM 節(jié)點(diǎn)) 來實(shí)現(xiàn)元素的渲染
ReactDOM.render(<組件名 />, document.getElementById('root'));
更新 UI 唯一的方式是創(chuàng)建一個(gè)全新的元素,并將其傳入 ReactDOM.render().
而在實(shí)踐中,大多數(shù) React 應(yīng)用只會(huì)調(diào)用一次 ReactDOM.render(),狀態(tài)更新是通過改變 State 來實(shí)現(xiàn)的.
組件
*每一個(gè) React 組件即是一個(gè) ES6 對(duì)象,對(duì)象內(nèi)部可以有屬性和方法,從而更好的操作組件內(nèi)部的頁面元素滤馍。React為了統(tǒng)一檢測(cè)變化岛琼,為每個(gè)React組件定義了兩個(gè)固定屬性,prop和state巢株,prop是React父組件在使用React組件時(shí)所傳入的屬性槐瑞,是由外部賦值的,而state只能通過內(nèi)部的構(gòu)造函數(shù)和setState方法賦值和修改阁苞。
組件分為函數(shù)組件與 class 組件
函數(shù)組件:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
class 組件:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
組件可以接收參數(shù),使用 this.props.參數(shù)名 來訪問該參數(shù)
const element = <Welcome name="Sara" />;
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
props 是只讀的,若要改變 props 的值,需要通過狀態(tài)提升和接口回調(diào)改變父組件中的值.
每個(gè)組件對(duì)象都會(huì)有props(properties的簡(jiǎn)寫)屬性
組件標(biāo)簽的所有屬性都保存在props中
對(duì) props 中的屬性值進(jìn)行類型限制和必要性限制
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}
組件名稱必須以大寫字母開頭,React 會(huì)將以小寫字母開頭的組件視為原生 DOM 標(biāo)簽
*雖然組件可以有兩種定義方式,但在后期實(shí)踐中,為了保證代碼的一致性,我通常使用 class 組件
1.class 組件可以指定 state.
2.class 組件可以為事件回調(diào)函數(shù)綁定 this.
3.定義為 class 更符合封裝組件的思想,而 function 容易使人產(chǎn)生誤解
組合組件
組件可以互相嵌套
<組件 1>
<組件 2 />
</ 組件 1>
提取組件
當(dāng)組件代碼被重復(fù)書寫時(shí),就應(yīng)當(dāng)考慮提取組件.
組件可以理解為移動(dòng)端的 view,我通常將提取一個(gè)組件形容為"抽象成一個(gè)類",這和前端的代碼習(xí)慣是不同的.
State
State 與 props 類似困檩,但是 state 是私有的祠挫,并且完全受控于當(dāng)前組件。
只有 class 組件可以使用 State
可以被理解為私有變量
state是組件對(duì)象最重要的屬性, 值是對(duì)象(可以包含多個(gè)數(shù)據(jù))
組件被稱為"狀態(tài)機(jī)", 通過更新組件的state來更新對(duì)應(yīng)的頁面顯示(重新渲染組件)
在 constructor(props) (class 構(gòu)造函數(shù))中可以為 state 賦初始值
class Clock extends React.Component { //只有 class 組件可以使用 State
constructor(props) { //這是一個(gè) class 構(gòu)造函數(shù)
super(props); //將 props 傳遞到父類的構(gòu)造函數(shù)中:
this.state = {屬性名: 初始值}; //給 state 賦初始值
}
render() {
return (
<div>{this.state.屬性名}</div>
);
}
}
使用組件時(shí)的注意事項(xiàng):
不要直接修改 state,而應(yīng)當(dāng)使用 this.setState({屬性名:屬性值})來修改 state
this.state.comment = 'Hello';//這種修改方式是無效的
構(gòu)造函數(shù)是唯一可以采用上述語句給 state 賦值的地方
state 的更新可能是異步的,若要立即更新state,可以使用函數(shù)
//箭頭函數(shù)
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
或
//普通函數(shù)
this.setState(function(state, props) {
return {
counter: state.counter + props.increment
};
});
setState()方法可以單獨(dú)更新每一個(gè)變量,而不會(huì)影響其他變量
數(shù)據(jù)是向下流動(dòng)的,父組件的 state 可以作為 props 傳遞給子組件,此特性也被稱為單向數(shù)據(jù)流
生命周期方法
componentDidMount() {
//組件已被掛載
}
componentWillUnmount() {
組件即將被卸載
}
生命周期
生命周期詳述
- 組件的三個(gè)生命周期狀態(tài):
- Mount:插入真實(shí) DOM
- Update:被重新渲染
- Unmount:被移出真實(shí) DOM
- React 為每個(gè)狀態(tài)都提供了勾子(hook)函數(shù)
- componentWillMount()
- componentDidMount()
- componentWillUpdate()
- componentDidUpdate()
- componentWillUnmount()
- 生命周期流程:
a. 第一次初始化渲染顯示: ReactDOM.render()
- constructor(): 創(chuàng)建對(duì)象初始化state
- componentWillMount() : 將要插入回調(diào)
- render() : 用于插入虛擬DOM回調(diào)
- componentDidMount() : 已經(jīng)插入回調(diào)
b. 每次更新state: this.setSate()
- componentWillUpdate() : 將要更新回調(diào)
- render() : 更新(重新渲染)
- componentDidUpdate() : 已經(jīng)更新回調(diào)
c. 移除組件: ReactDOM.unmountComponentAtNode(containerDom)
- componentWillUnmount() : 組件將要被移除回調(diào)
重要的勾子
render(): 初始化渲染或更新渲染調(diào)用
componentDidMount(): 開啟監(jiān)聽, 發(fā)送ajax請(qǐng)求
componentWillUnmount(): 做一些收尾工作, 如: 清理定時(shí)器
事件處理
React 事件的命名采用小駝峰式
使用 JSX 語法時(shí)你需要傳入一個(gè)函數(shù)作為事件處理函數(shù)悼沿,而不是一個(gè)字符串
//html
<button onclick="activateLasers()" />
//React
<button onClick={activateLasers} />
在 React 中,想要阻止默認(rèn)事件的行為,需要調(diào)用 preventDefault 方法.
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
在回調(diào)函數(shù)中想要使用 this,必須在構(gòu)造函數(shù)中為該回調(diào)函數(shù)綁定 this
// 為了在回調(diào)中使用 this
等舔,這個(gè)綁定是必不可少的
this.handleClick = this.handleClick.bind(this);
可以通過以下方法給回調(diào)函數(shù)傳參,e 會(huì)作為第二個(gè)參數(shù)隱式傳遞
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
通過 event.target 得到發(fā)生事件的DOM元素對(duì)象
<input onFocus={this.handleClick}/>
handleFocus(event) {
event.target //返回input對(duì)象
}
條件渲染
可以通過 if 語句結(jié)合 return 組件 來決定顯示哪個(gè)組件
render() {
const isLoggedIn = this.state.isLoggedIn;
let button;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
也可以通過 && (邏輯與運(yùn)算符)的短路特性來決定是否渲染組件
function Mailbox(props) {
return (
<div>
{條件 && 組件}
</div>
);
}
之所以能這樣做,是因?yàn)樵?JavaScript 中糟趾,true && expression 總是會(huì)返回 expression, 而 false && expression 總是會(huì)返回 false慌植。
也可以通過三目運(yùn)算符來決定渲染哪個(gè)組件
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{條件 ? (<組件 1 />) : (<組件 2 />)}
</div>
);
}
可以通過讓 rander() 方法直接返回 null 來阻止組件渲染
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
Warning!
</div>
);
}
在組件的 render 方法中返回 null 并不會(huì)影響組件的生命周期。
componentDidUpdate 依然會(huì)被調(diào)用义郑。
key
key 幫助 React 識(shí)別哪些元素改變了蝶柿,比如被添加或刪除。因此你應(yīng)當(dāng)給數(shù)組中的每一個(gè)元素賦予一個(gè)確定的標(biāo)識(shí)非驮。
在一個(gè)列表中,如果沒有傳遞 key,將會(huì)看到一個(gè)警告 a key should be provided for list items交汤,意思是當(dāng)你創(chuàng)建一個(gè)元素時(shí),必須包括一個(gè)特殊的 key 屬性院尔。
一個(gè)元素的 key 最好是這個(gè)元素在列表中擁有的一個(gè)獨(dú)一無二的字符串蜻展。通常,我們使用來自數(shù)據(jù) id 來作為元素的 key
當(dāng)元素沒有確定 id 的時(shí)候邀摆,萬不得已你可以使用元素索引 index 作為 key:
如果你選擇不指定顯式的 key 值纵顾,那么 React 將默認(rèn)使用索引用作為列表項(xiàng)目的 key 值。
總之,一個(gè)好的經(jīng)驗(yàn)法則是:在 map() 方法中的元素需要設(shè)置 key 屬性栋盹。
在同級(jí)元素中,key 必須是獨(dú)一無二的.
在 JSX 中可以直接嵌入 map()
const listItems = numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
);
其返回值為一個(gè)包含條件函數(shù)中元素組成的數(shù)組
//可以直接在大括號(hào)中嵌入
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
*這么做有時(shí)可以使你的代碼更清晰施逾,但有時(shí)這種風(fēng)格也會(huì)被濫用。就像在 JavaScript 中一樣例获,何時(shí)需要為了可讀性提取出一個(gè)變量汉额,這完全取決于你。但請(qǐng)記住榨汤,如果一個(gè) map()
嵌套了太多層級(jí)蠕搜,那可能就是你提取組件的一個(gè)好時(shí)機(jī)。
*表單元素沒用過
表單&受控組件
在 React 里收壕,HTML 表單元素的工作方式和其他的 DOM 元素有些不同妓灌,這是因?yàn)楸韱卧赝ǔ?huì)保持一些內(nèi)部的 state。
使用受控組件來實(shí)現(xiàn)表單元素的效果,理解起來非常簡(jiǎn)單:
設(shè)置表單元素的 value={this.state.value},并監(jiān)聽元素的 onChange 方法,改變 state
當(dāng) value 設(shè)置為 undefined 或者 null 的時(shí)候,受控組件是可被編輯的,避免這種情況可以給 state 賦一個(gè)初值.
狀態(tài)提升
通常蜜宪,多個(gè)組件需要反映相同的變化數(shù)據(jù)虫埂,這時(shí)我們建議將共享狀態(tài)提升到最近的共同父組件中去。
步驟:
1.父組件定義一個(gè) state 的屬性,將該屬性作為 props 傳遞至子組件中
2.子組件中使用 this.props 來訪問該屬性
3.當(dāng)父組件中的屬性產(chǎn)生變化時(shí),子組件會(huì)相應(yīng)地被更新
4.當(dāng)一個(gè)屬性需要由子組件傳遞給父組件時(shí),需要采用回調(diào)
5.父組件定義并實(shí)現(xiàn)一個(gè)回調(diào)方法,在該方法中接收參數(shù)改變屬性,將該方法傳遞給子組件
6.當(dāng)該狀態(tài)需要改變時(shí),子組件調(diào)用該方法,并傳遞參數(shù)
7.父組件中的狀態(tài)被修改,引發(fā)狀態(tài)變化,子組件被刷新
在 React 應(yīng)用中圃验,任何可變數(shù)據(jù)應(yīng)當(dāng)只有一個(gè)相對(duì)應(yīng)的唯一“數(shù)據(jù)源”掉伏。通常,state 都是首先添加到需要渲染數(shù)據(jù)的組件中去。然后斧散,如果其他組件也需要這個(gè) state供常,那么你可以將它提升至這些組件的最近共同父組件中。你應(yīng)當(dāng)依靠[自上而下的數(shù)據(jù)流],而不是嘗試在不同組件間同步 state颅湘。
雖然提升 state 方式比雙向綁定方式需要編寫更多的“樣板”代碼话侧,但帶來的好處是荤懂,排查和隔離 bug 所需的工作量將會(huì)變少闷游。由于“存在”于組件中的任何 state朽砰,僅有組件自己能夠修改它,因此 bug 的排查范圍被大大縮減了鹿寨。此外,你也可以使用自定義邏輯來拒絕或轉(zhuǎn)換用戶的輸入薪夕。
*這其實(shí)就是 block 傳值
其他:
refs
組件內(nèi)的標(biāo)簽都可以定義 ref 屬性來標(biāo)識(shí)自己
在父組件調(diào)用子組件方法時(shí)會(huì)使用到 ref
React 和 Angular 的區(qū)別:
React 涉及到更多的 JavaScript 代碼(JavaScript ES6,JSX),Angular 則更多寫 HTML(特殊的 html 語法),邏輯部分采用 TypeScript
React 單向數(shù)據(jù)綁定,Angular 雙向數(shù)據(jù)綁定
React 一個(gè)組件幾乎不需要 .html 文件,Angular 通常需要一個(gè).html 文件(可以說 Angular 沒有組件化的概念)
React 一個(gè).ts 文件中可以有多個(gè)組件,Angular 一個(gè).ts 文件是一個(gè)組件
React 項(xiàng)目中使用 .less,Angular 項(xiàng)目中使用 .scss(并不絕對(duì),但我們目前做的兩個(gè)項(xiàng)目是這樣的)
相對(duì)來說,React 比 Angular 更加貼近移動(dòng)端構(gòu)建界面的思想,對(duì)我這種移動(dòng)端開發(fā)人員來說也更容易理解.
組合
React 有十分強(qiáng)大的組合模式脚草。我們推薦使用組合而非繼承來實(shí)現(xiàn)組件間的代碼重用。
組件的組合
組件化編寫功能流程:
1.拆分組件
2.實(shí)現(xiàn)靜態(tài)組件(只有靜態(tài)界面原献,沒有動(dòng)態(tài)數(shù)據(jù)和交互)
3.實(shí)現(xiàn)動(dòng)態(tài)組件
- 實(shí)現(xiàn)初始化數(shù)據(jù)動(dòng)態(tài)顯示
- 實(shí)現(xiàn)交互功能
我采用的界面編寫流程:自上而下地構(gòu)建界面
區(qū)別一下組件的 props 和 state 屬性
state: 組件自身內(nèi)部可變化的數(shù)據(jù)
props: 從組件外部向組件內(nèi)部傳遞數(shù)據(jù), 組件內(nèi)部只讀不修改
React 并不需要繼承,所以其核心和面向?qū)ο蟮奶匦?封裝,繼承,多態(tài))有一定的區(qū)別
個(gè)人理解:
其中封裝可以理解為組件的提取
由于沒有繼承關(guān)系,所以也不存在方法覆蓋的概念,也就沒有多態(tài),同時(shí)也就引發(fā)了諸如界面樣式?jīng)]有公開 API 就無法修改之類的問題,在面向?qū)ο笾锌梢允褂梅椒ǜ采w來實(shí)現(xiàn)這一點(diǎn)
其本質(zhì)我認(rèn)為是函數(shù)式編程的思想,通過其組件定義方式 function ,和新特性 HOOK 中極力避免使用 class 關(guān)鍵字等行為也可以看出這一點(diǎn)
在文章寫到這里,我深入地思考了 React 框架的特性,得出了其思想是 既是面向?qū)ο缶幊?又注重函數(shù)式編程 的結(jié)論.
React 還是無法避免面向?qū)ο蟮奶攸c(diǎn),因?yàn)榻M件是可以使用 extends 關(guān)鍵字繼承的,盡管在開發(fā)時(shí)我們經(jīng)常忽略它.
React 同時(shí)具有函數(shù)式編程的諸多特征,
1.函數(shù)不能更改輸入?yún)?shù),
2.自上而下的單向數(shù)據(jù)流,
3.無狀態(tài)組件(不需要 state 的組件)也是通過 function 來創(chuàng)建,
4.高階組件的特性也更偏向于函數(shù)思想而不是繼承.
(高階組件:接收一個(gè)組件作為參數(shù),返回一個(gè)包含參數(shù)組件的新組件,可以理解為接收一個(gè)子視圖,返回一個(gè)包含有子視圖的父視圖,這種思想類似于高階函數(shù),即接收一個(gè)函數(shù)作為參數(shù),并返回一個(gè)經(jīng)過參數(shù)函數(shù)運(yùn)算過的返回值).
這對(duì)我來說這是一種全新的體驗(yàn),關(guān)于編程思想上次對(duì)我造成如此大的沖擊還是在學(xué)習(xí)和使用 swift 的時(shí)候.
函數(shù)式編程的特點(diǎn):
1.閉包和高階函數(shù)
閉包即接口,可以通過傳值來操作對(duì)象
高階函數(shù)即接收一個(gè)函數(shù)作為參數(shù),并返回一個(gè)經(jīng)過參數(shù)函數(shù)運(yùn)算過的返回值,甚至返回值可以是一個(gè)函數(shù)
2.惰性計(jì)算
在惰性計(jì)算中馏慨,表達(dá)式不是在綁定到變量時(shí)立即計(jì)算,而是在求值程序需要產(chǎn)生表達(dá)式的值時(shí)進(jìn)行計(jì)算姑隅。
可以理解為 state 改變時(shí)只對(duì)必要的組件記性改變,而其余部分不變.
3.遞歸
簡(jiǎn)單來說就是自己調(diào)用自己
4.函數(shù)是"一等公民"
函數(shù)可以作為參數(shù)傳遞,也可以作為返回值
5.沒有副作用
即不改變?nèi)雲(yún)?只傳遞一個(gè)新參數(shù)作為返回值
6.確定性
給定的輸入永遠(yuǎn)產(chǎn)生同樣的輸出,這和多態(tài)的思想是相反的
函數(shù)式編程提倡使用函數(shù)的組合來實(shí)現(xiàn)某些功能,這和面向?qū)ο笾惺褂美^承的思想是相悖的,我認(rèn)為造成其編程思想根本區(qū)別的點(diǎn)在于前端使用的 html 語言其實(shí)就是通過組合各種基本元素來實(shí)現(xiàn)各種效果的,而且 React 框架能實(shí)現(xiàn)的部分按照傳統(tǒng)的 MVC 架構(gòu)來看其實(shí)只有 V 和 C,也就是視圖和控制器,這里的控制器也只是進(jìn)行網(wǎng)絡(luò)請(qǐng)求和頁面邏輯的處理,這和移動(dòng)端與后端的思想是不同的,移動(dòng)端和后端需要進(jìn)行業(yè)務(wù)邏輯處理而不僅僅是界面邏輯,而在單純的前端開發(fā)中,這些工作大多是由后端完成的,所以函數(shù)式編程的思想更適用于前端開發(fā).
關(guān)于不同的編程范式,其實(shí)沒有優(yōu)劣之分,完全可以做到博取眾長,互相融合.在移動(dòng)端開發(fā)時(shí)我也接觸過函數(shù)式編程,swift 就是一門融合了函數(shù)式編程思想的語言,swift 中的四大基本類型包括 類,函數(shù),結(jié)構(gòu)體和枚舉.
swift 中的基本數(shù)據(jù)類型都是結(jié)構(gòu)體類型
swift 中的數(shù)組,字典,字符串都是類類型
swift 中的函數(shù)也是一種類型,其可以作為參數(shù)被傳遞,也可以作為一種類型被接口聲明
有的時(shí)候我們只是專注于寫代碼,實(shí)現(xiàn)各種業(yè)務(wù)和功能,其實(shí)程序員不僅僅是一個(gè)單純寫代碼完成任務(wù)的職業(yè),我們是在用代碼描述世界,甚至是創(chuàng)造世界,所以有的時(shí)候我寫代碼寫著寫著就陷入了對(duì)這個(gè)世界深深的思考當(dāng)中...這不僅僅是空想,其實(shí)程序員們?cè)谌绾螛?gòu)建世界的問題上已經(jīng)陷入了一個(gè)大坑,那就是人工智能,人工智能就其本質(zhì)而言,是對(duì)人的思維的信息過程的模擬,人工智能到底該如何實(shí)現(xiàn),我們可以在百度上查看到人工智能涉及到的學(xué)科包括
哲學(xué)和認(rèn)知科學(xué)
數(shù)學(xué)
神經(jīng)生理學(xué)
心理學(xué)
仿生學(xué)
語言學(xué)
計(jì)算機(jī)科學(xué)
自動(dòng)化
信息論
控制論
不定性論
社會(huì)結(jié)構(gòu)學(xué)
甚至還有科學(xué)發(fā)展觀
可見這是一門極其深?yuàn)W的技術(shù),這也側(cè)面印證了我們程序員其實(shí)是在想辦法在計(jì)算機(jī)上描述和重現(xiàn)這個(gè)世界.所以程序員在生活中,相比普通人來說,需要對(duì)這個(gè)世界有更加深刻的認(rèn)知和理解才行,程序員需要走的路還有很長很長.
當(dāng)然這和 React 開發(fā)沒有什么聯(lián)系了..言歸正傳.
React 是我第一個(gè)系統(tǒng)學(xué)習(xí)的前端框架,也是第一次接觸 JavaScript ,并有了項(xiàng)目實(shí)戰(zhàn)經(jīng)驗(yàn),在接下來的 Angular 學(xué)習(xí)中,我會(huì)繼續(xù)探索 JS 和前端開發(fā)的特性,總結(jié)經(jīng)驗(yàn),提升自我.