本篇文章并不是按照官網(wǎng)API由易到難講解,而是按照我所做的項(xiàng)目實(shí)踐得出的結(jié)論靖苇。可能有些寫的并不是絕對(duì)的完美的方案班缰,我們可以一起討論贤壁,并且我也是在學(xué)習(xí)當(dāng)中〔和可能有自己遇到的一些坑的一些解決方案脾拆,希望能在工作中幫助到大家??。
React基本概念還是需要看下官網(wǎng)API莹妒,了解并熟知React的語(yǔ)法概念和組件化思想名船,生命周期要熟悉。ES6常用特性要熟悉旨怠。
看身邊的同事渠驼,意識(shí)到不一定是前端可以學(xué)會(huì)React,如果你會(huì)其他語(yǔ)言鉴腻,同樣也能入門迷扇。
關(guān)于React腳手架 create-react-app 安裝配置我在另一篇幅有講:http://www.reibang.com/p/b168c47a7620
React是什么?
React是一個(gè)聲明式爽哎,高效且靈活的用于構(gòu)建用戶界面的JavaScript庫(kù)谋梭。使用React可以將一些簡(jiǎn)短、獨(dú)立的代碼片段組合成復(fù)雜的UI界面倦青,這些代碼片段被稱作“組件”瓮床。
class HelloWorld extends Component {
//初始化組件狀態(tài)
constructor(props) {
super(props)
this.state = {
loading: false
}
}
componentDidMount(){
//調(diào)用API
}
render() {
return <div>hello world!</div>
}
}
export default HelloWorld
由此看出以上是一個(gè)簡(jiǎn)單的組件,this.state是對(duì)狀態(tài)的一個(gè)初始化賦值的概念。它是一個(gè)有狀態(tài)的組件隘庄,具有完整的生命周期概念踢步。但項(xiàng)目中不僅僅是只用這種有狀態(tài)組件,還有其他組件類型丑掺。
而無(wú)狀態(tài)組件是通過(guò)無(wú)狀態(tài)的函數(shù)創(chuàng)建的获印,它是一種只負(fù)責(zé)展示的純組件。無(wú)狀態(tài)組件的特點(diǎn)是不需要管理組件狀態(tài)state街州,數(shù)據(jù)直接通過(guò)props傳入即可兼丰,這也符合React單向數(shù)據(jù)流的思想。
這里可以科普下無(wú)狀態(tài)組件的概念:
無(wú)狀態(tài)組件
無(wú)狀態(tài)組件可以通過(guò)減少繼承Component而來(lái)的生命周期函數(shù)而達(dá)到性能優(yōu)化的效果唆缴。從本質(zhì)上來(lái)說(shuō)鳍征,無(wú)狀態(tài)組件就是一個(gè)單純的render函數(shù),所以無(wú)狀態(tài)組件的缺點(diǎn)也是顯而易見(jiàn)的面徽。因?yàn)樗鼪](méi)有shouldComponentUpdate生命周期函數(shù)艳丛,所以每次state更新,它都會(huì)重新繪制render函數(shù)趟紊。
對(duì)于無(wú)狀態(tài)組件的函數(shù)式生命方法氮双,不僅可以提高代碼的可閱讀行,還能大大的減少代碼量霎匈,提高代碼的復(fù)用率戴差。
以下是我項(xiàng)目中所寫的無(wú)狀態(tài)組件。
const ScaleScorePage = (props) => {
const patientScales = props.patientStatus.get('newScales')
return (
<div className={styles.commonDiagnosisWrapper}>
<div className={styles.commonDiagnosisTitle}>
<h3>卒中嚴(yán)重程度評(píng)估</h3>
</div>
{patientScales &&
<div className={styles.commonDiagnosisInner}>
<Row>
{renderBaseScoreInner(patientScales)}
</Row>
</div>
}
<div className={styles["text-right"]} style={{display: 'none'}}><Button>查看出院時(shí)量表評(píng)分</Button></div>
</div>
)
}
export default ScaleScorePage
以上代碼中props是父組件傳遞過(guò)來(lái)的屬性铛嘱。此時(shí)就用到了父組件如何向子組件通信暖释,父組件通過(guò)props給子組件傳遞數(shù)據(jù)。如下示例:
<ScaleScorePage patientStatus={patientStatus}/>
上面的patientStatus就是屬性值通過(guò)props傳遞給子組件ScaleScorePage弄痹。
思考:如何在這種無(wú)狀態(tài)組件中想用到生命周期的概念呢?這個(gè)就要用到React 16.8的新增特性Hook,它可以讓你在不編寫class的情況下使用state以及其他的React特性嵌器。
Hook
最近項(xiàng)目中用到的示例:
主要用到的就是 useState ,以及 useEffect
import React, { useEffect, useState } from "react"
import {Button} from 'antd';
import {connect} from "react-redux";
import styles from '../../css/diagnosis/diagnosis.module.css'
import {getPatientComplaint} from "../../actions";
const PatientStatement = (props) => {
const {patientID,patientComplaint} = props
const [basePatientDetails, onPatientStatementChange] = useState(false)
useEffect(() =>{props.getPatientComplaint(patientID)},[])
return (
<div className={styles.commonDiagnosisWrapper}>
<div className={`${styles.commonDiagnosisTitle} ${styles.commonDiagnosisTitle1}`}>
<h3>主訴</h3>
<Button style={{display: 'none'}} type="primary" key="ignore" onClick={()=>onPatientStatementChange(!basePatientDetails)}>
{basePatientDetails ? '保存' : '編輯'}
</Button>
<span style={{float: 'right'}}>記錄時(shí)間: 暫無(wú)</span>
</div>
<ul>
{patientComplaint.map((item,idx)=><li key={item.id}>{item}</li>)}
</ul>
</div>
)
}
const mapStateToProps = state => {
return {
patientComplaint: state.diagnosis.get('patientComplaint')
}
}
export default connect(mapStateToProps,{getPatientComplaint})(PatientStatement)
由以上get的知識(shí)點(diǎn)的涵蓋面可能有點(diǎn)多肛真,首先可以忽略redux這部分內(nèi)容,這個(gè)可以單獨(dú)幾個(gè)篇幅去講解爽航。如何從父組件向子組件傳遞值上面已經(jīng)講過(guò)蚓让,下面就是講解useState.
useState
// 聲明一個(gè)叫做basePatientDetails的 state 變量,
const [basePatientDetails, onPatientStatementChange] = useState(false)
聲明一個(gè)叫做basePatientDetails的 state 變量讥珍,初始化值設(shè)置為false历极,并且在onPatientStatementChange方法中改變state變量的值。
useEffect
Effect Hook 可以讓你在函數(shù)組件中執(zhí)行副作用操作衷佃。如果你熟悉React class的生命周期趟卸,你可以把useEffect 看作是componentDidMount , componentDidUpdate和componentWillUnmount這三個(gè)函數(shù)的組合。
useEffect(() ={ props.getPatientComplaint(patientID) } ) //xxxx
useEffect(() ={ props.getPatientComplaint(patientID) },[] )
??注意:以上寫法是有個(gè)箭頭函數(shù),然后執(zhí)行了一個(gè)API接口調(diào)用锄列。因?yàn)樗哂猩芷诘母拍钔荚疲@樣又陷入萬(wàn)惡的循環(huán)中,所以解決辦法是在結(jié)尾加 [].
css樣式模塊化
另外在樣式上邻邮,最開(kāi)始寫項(xiàng)目的時(shí)候竣况,發(fā)現(xiàn)引用的css樣式是全局的樣式,會(huì)經(jīng)常出現(xiàn)樣式覆蓋問(wèn)題筒严。這樣對(duì)于團(tuán)隊(duì)開(kāi)發(fā)是非常不友好的丹泉。后來(lái)在項(xiàng)目中對(duì)css起的名字做了研究,xxx.module.css這樣自動(dòng)對(duì)css樣式進(jìn)行模塊化管理鸭蛙。只需要在組件引用的時(shí)候使用
//如果引用多個(gè)樣式文件
import styles from '../../css/diagnosis/diagnosis.module.css'
import iStyles from '../../css/infomation.module.css'
使用時(shí)候這樣用,以下有單個(gè)類名以及多個(gè)類名示例:
<div className={styles.outer}>
<div className={`${styles.inner} ${iStyles.border}`}>
</div>
解構(gòu)賦值
const { patientID,patientComplaint } = props
//等價(jià)于
const patientID = props.patientID
const patientComplaint = props.patientComplaint
列表 & key
map方法非常實(shí)用摹恨。
<ul>
{patientComplaint.map((item,idx)=><li key={item.id}>{item}</li>)}
</ul>
由此map方法使用前提必須是一個(gè)數(shù)組,參數(shù)( currentValue, index, arr )规惰。
currentValue (必須睬塌。當(dāng)前元素的值)
index (可選。當(dāng)前元素的索引值)
arr (可選歇万。當(dāng)前元素屬于的數(shù)組對(duì)象)
另外:還會(huì)有數(shù)據(jù)改造的情況(出現(xiàn)于后臺(tái)字段跟前端所用字段不一致)
const renderExamTitle = (item) => {
return <Fragment><span>{item.examItem||''}</span><span style={{float: 'right'}}>{item.examUnit||''}</span></Fragment>
}
const renderExamResult = (item, params, style1) => {
return <Fragment><span style={style1}>{item.examResult?item.examResult:'無(wú)'} {params}</span></Fragment>
}
/**處理數(shù)值變化值*/
const handlerExamResult = (item) => {
switch (item.examStatus) {
case 'u':
return renderExamResult(item, '↑', {color: '#d90f0f'})
case 'd':
return renderExamResult(item, '↓', {color: '#d90f0f'})
default:
return renderExamResult(item, '');
}
}
const handlerBody = (data) => {
// 接口數(shù)據(jù)映射處理
return data.map((item, index) =>({
key: index,
examItem: renderExamTitle(item),
examResult: handlerExamResult(item),
maleStd: item.maleStd
}))
}
思考??:
假設(shè)如果后臺(tái)給的數(shù)據(jù)是長(zhǎng)得這個(gè)樣子揩晴,需要前端頁(yè)面進(jìn)行循環(huán)處理結(jié)構(gòu)。
const options = {
"正程盎牵或近乎正常": "0-1分",
"輕度卒中/小卒中": "2-4分",
"中度卒中": "5-15分",
"中-重度卒中": "16-20分",
"重度卒中": "21-42分"}
提示??:
console.log( Object.keys(options) )
//expected output: ["正沉蚶迹或近乎正常", "輕度卒中/小卒中", "中度卒中", "中-重度卒中", "重度卒中"]
console.log( Object.values(options) )
//exoected output: ["0-1分", "2-4分", "5-15分", "16-20分", "21-42分"]
由此你是不是有思路了。get it ??寒锚!
<ul className={styles.scaleScoreText}>
{Object.keys(options).map((itm, idx) => <li key={idx}>{options[itm]}<p>{itm}</p></li>)}
</ul>
React 中的三元運(yùn)算符
如果在jsx語(yǔ)句中用到if-else 語(yǔ)句進(jìn)行條件渲染怎么辦劫映?可以使用三元運(yùn)算符:
{
nodeDetails.isFinal?
<div>有數(shù)據(jù) </div> : <div>暫無(wú)結(jié)果</div>
}
<div>參考范圍 {item.range=== null?'暫無(wú)':item.range}</div>
如果只返回條件渲染的一方面,可以使用&&運(yùn)算符
{
data.checks.length>0 &&<div>顯示....</div>
}
補(bǔ)充:
1.let arr = ['a','b','c'] 改造成===> obj = {a:1,b:1,c:1}
let arr = ['a','b','c']
let obj = {}
arr.map(item=>obj[item] = 1)
console.log(obj)
未完待續(xù)刹前。泳赋。。