自React版本16.8之后,

增加了Hook的新特性,其中包含有useState,useEffect,useContex的3種新方式。
眾所周知,在React中一切元素都是組件化編程模式,主要有2種組件定義方式,一種是在es6語(yǔ)法下通過(guò)class類提供的繼承自React.Component 的定義方式,還有一種是函數(shù)式組件,即如以function定義的函數(shù)組件。
一.React安裝相關(guān)
工欲善其事,必先利其器。
在我們想研究學(xué)習(xí)React的useState用法前,首先我們先要把React環(huán)境給配置好,當(dāng)然這塊網(wǎng)絡(luò)教程也很多,這里就簡(jiǎn)單說(shuō)明并過(guò)濾一下的情況。
1.React基本介紹和安裝步驟說(shuō)明
1.1.React基本介紹
眾所周知,React是Facebook為了替代傳統(tǒng)的JS下的MVC框架不滿意,所以先行開發(fā)的一套供其內(nèi)部使用的前端框架,后于2013年對(duì)外開源,然后發(fā)展至今的一套前端框架。所以既然React實(shí)現(xiàn)的底層是前端框架,那么就要求想學(xué)習(xí)會(huì)React的開發(fā)者,首先要對(duì)傳統(tǒng)的HTML,CSS以及JS有一定的了解和開發(fā)經(jīng)驗(yàn),不然后面會(huì)吃一些褲頭的。
對(duì)于React的安裝其實(shí)很簡(jiǎn)單,在安裝React之前,首先需要安裝Node和npm環(huán)境配置
1.2.安裝Node和npm
這塊具體安裝方式,網(wǎng)絡(luò)一搜一大堆,就不多做介紹了,只需要強(qiáng)調(diào)一點(diǎn),按照的node和npm版本最好分別在14和5.2之后,這樣可以用npm自帶的包來(lái)創(chuàng)建react項(xiàng)目,實(shí)現(xiàn)快速開發(fā)的目的。
1.3.npx create-react-app my-app 命令創(chuàng)建我們的React程序
注意這里的npx 是在node14和npm5.2之后npm自帶的一個(gè)管理包工具,當(dāng)然作為新手,一般不建議用該命令去創(chuàng)建項(xiàng)目,而是后面要加上一點(diǎn)內(nèi)容,如后面的我們的第一個(gè)React程序中所示。
另外需要注意的是在React中創(chuàng)建項(xiàng)目名稱中不能有大寫字母,不然會(huì)報(bào)如下錯(cuò)誤

2.我們的第一個(gè)React程序
我們創(chuàng)建第一個(gè)React程序最好采用如下的方式,即為
npx create-react-app hello-world --template typescript

之后按照提示分別執(zhí)行上圖中的2個(gè)命令
cd hello-world
yarn start
之后我們的第一個(gè)React項(xiàng)目就顯示在眼前,如下所示:

通過(guò)該命令創(chuàng)建的React程序支持ts語(yǔ)法,關(guān)于ts的比js到底多了哪些功能,詳細(xì)可參考這篇文章:TypeScript超詳細(xì)入門教程(上)
這里匯總下,簡(jiǎn)單來(lái)說(shuō),通過(guò)ts來(lái)替代js實(shí)現(xiàn)的方式,因?yàn)?strong>js是弱類型編碼語(yǔ)言,在開發(fā)中無(wú)法及時(shí)發(fā)現(xiàn)錯(cuò)誤和漏洞;
如果通過(guò)ts就可以讓開發(fā)者在編碼過(guò)程中養(yǎng)成良好的開發(fā)習(xí)慣,從而實(shí)現(xiàn)可以讓開發(fā)者(特別是新手)在編碼階段就及早發(fā)現(xiàn)一些不規(guī)范的命名了,變量賦值了,定義了等低級(jí)錯(cuò)誤。
而且ts還比js多了更多的解決問(wèn)題的方式展示,總之ts比js實(shí)現(xiàn)更友好一些。
二.userState功能展示說(shuō)明
好了,前面鋪墊了那么多,終于到了本篇文章的重點(diǎn)了,本篇文章的重點(diǎn)即為通過(guò)React的函數(shù)式編程組件在useState技術(shù)的幫助下實(shí)現(xiàn)一個(gè)簡(jiǎn)單的增刪改查案例展示。
1.hook助攻下useState領(lǐng)銜函數(shù)式組件大發(fā)展
首先我們來(lái)簡(jiǎn)單討論下函數(shù)式組件和傳統(tǒng)的類組件2種方式定義組件的異同點(diǎn),類組件定義相對(duì)好理解一些;
因?yàn)闊o(wú)論是通過(guò)props來(lái)設(shè)置屬性,還是通過(guò)state來(lái)設(shè)置狀態(tài)從而實(shí)現(xiàn)改變對(duì)應(yīng)的dom實(shí)現(xiàn)頁(yè)面刷新,都是一環(huán)套一環(huán)的,好理解一些,
但其缺點(diǎn)是對(duì)應(yīng)與組件狀態(tài)必須要么實(shí)時(shí)跟蹤,要么必須通過(guò)數(shù)據(jù)改變,然后setstate對(duì)應(yīng)的組件狀態(tài),界面才能刷新,實(shí)現(xiàn)相對(duì)麻煩;
如果在16.8之前React沒(méi)有提供這些hook方法的話,函數(shù)式組件由于本身實(shí)質(zhì)是一個(gè)函數(shù),所以無(wú)法包含生命周期方法,還有一些屬性無(wú)法像類一樣部分擁有等缺陷,大部分情況下都被開發(fā)者束之高閣。
但在16.8之后特別是useState和useEffect,一個(gè)解決了數(shù)據(jù)改變,界面就可以及時(shí)刷新功能,一個(gè)解決了生命周期實(shí)現(xiàn)的方式。本篇主要講解useState的用法,那么我們就來(lái)看看useState的神功吧!
2.userState技術(shù)功能實(shí)現(xiàn)小案例說(shuō)明
在本案例中通過(guò)定義一個(gè)App的函數(shù)和SomeChild類,來(lái)實(shí)現(xiàn)對(duì)該App函數(shù)組件的增刪改功能,具體表現(xiàn)為通過(guò)輸入框輸入該SomeChild類的名字,年齡,學(xué)校后,實(shí)現(xiàn)生成一個(gè)孩子;
當(dāng)點(diǎn)擊 不滿意-重生 按鈕時(shí),相當(dāng)于修改,即可以實(shí)現(xiàn)編輯孩子對(duì)應(yīng)的屬性,編輯完畢之后,繼續(xù)點(diǎn)擊生一個(gè)按鈕時(shí),實(shí)現(xiàn)對(duì)孩子信息的編輯,也可以點(diǎn)擊打掉-重來(lái),則相當(dāng)于刪除功能,即實(shí)現(xiàn)對(duì)該孩子的刪除這么一個(gè)小功能實(shí)現(xiàn)。
3.useState代碼實(shí)現(xiàn)說(shuō)明
可以分為3部曲,即為導(dǎo)——>定——>用三步曲。
3.1.導(dǎo),即導(dǎo)入類庫(kù),如下所示
import React,{useState} from 'react';
3.2.定,即定義被useState所包裹的屬性才能數(shù)據(jù)變了,界面跟著變的效果。
說(shuō)到這里,可以閑扯一點(diǎn)關(guān)于useState的功能實(shí)現(xiàn)原理,
即簡(jiǎn)單來(lái)說(shuō)為MVVM模型的實(shí)現(xiàn),數(shù)據(jù)和界面互相綁定,從而實(shí)現(xiàn)對(duì)數(shù)據(jù)一旦改變,界面就跟著改變的效果,
這點(diǎn)類似iOS中的KVO,Vue中的watch觀察者模式功能。
// 定義類的userState下的變量
const [child,creatChild] = useState(new SomeChild())
const [childList,setChildList] = useState([])
3.3.用,用是核心,要怎么用呢
關(guān)鍵在于怎么理解定義中的如child creatChild功能,其實(shí),child就是這個(gè)數(shù)據(jù)變化的一個(gè)臨時(shí)變量(可以這么理解),
即當(dāng)前要操作的對(duì)象,而creatChild就是對(duì)child進(jìn)行改變的一個(gè)開關(guān),相當(dāng)于調(diào)用了一個(gè)creatChild的方法。
我們只需要傳遞改變后的child,底層就幫我們實(shí)現(xiàn)了按照我們新傳遞的child去改變界面,從而實(shí)現(xiàn)數(shù)據(jù)改變,界面就跟著改變的效果。
3.3.1.輸入框的創(chuàng)建和修改代碼實(shí)現(xiàn)功能
if(child.childId) { // 修改重生
let childIndex = childList.findIndex((p) => p.childId == child.childId)
childList[childIndex]= _.clone(child)
setChildList(childList)
}
else { // 簡(jiǎn)單創(chuàng)建
child.childId = new Date().getTime();
childList.unshift(_.clone(child))
setChildList(childList)
}
// 這里必須要調(diào)用一次 creatChild不然數(shù)據(jù)不會(huì)顯示到列表中
// creatChild(_.clone(child))
creatChild({childName:null,childAge:null,childId:null,childSchool:null})
console.log("save-childList",childList)
3.3.2.每條孩子信息刪除和修改代碼實(shí)現(xiàn)功能
<button onClick={()=>{
// 這里必須把所有屬性寫全乎了,或者修改部分的話,就用...語(yǔ)法
creatChild({childName:item.childName,childAge:item.childAge,childSchool:item.childSchool,childId:item.childId})
}}>不滿意-重生</button>
<button onClick={()=>{
let tempChildList = childList.filter((p) => p.childId != item.childId)
console.log("tempChildList",tempChildList)
setChildList(tempChildList)
}}>打掉-再來(lái)</button>
最后放上一個(gè)本篇中通過(guò)useState方式實(shí)現(xiàn)的效果展示:

具體代碼實(shí)現(xiàn)詳見(jiàn)地址為:我的userState和MobX簡(jiǎn)單實(shí)現(xiàn)Demo
最后,有什么問(wèn)題,咱們?cè)u(píng)論區(qū)見(jiàn)哈!