入手react项目三个月的心得( 纯干货 )

本篇文章并不是按照官网API由易到难讲解,而是按照我所做的项目实践得出的结论。可能有些写的并不是绝对的完美的方案,我们可以一起讨论,并且我也是在学习当中。可能有自己遇到的一些坑的一些解决方案,希望能在工作中帮助到大家😄。
React基本概念还是需要看下官网API,了解并熟知React的语法概念和组件化思想,生命周期要熟悉。ES6常用特性要熟悉。
看身边的同事,意识到不一定是前端可以学会React,如果你会其他语言,同样也能入门。
关于React脚手架 create-react-app 安装配置我在另一篇幅有讲:https://www.jianshu.com/p/b168c47a7620

React是什么?

React是一个声明式,高效且灵活的用于构建用户界面的JavaScript库。使用React可以将一些简短、独立的代码片段组合成复杂的UI界面,这些代码片段被称作“组件”。

class HelloWorld extends Component {
    //初始化组件状态
    constructor(props) {
        super(props)
        this.state = {
            loading: false
        }
    }
  componentDidMount(){
      //调用API
  }
  render() {
        return <div>hello world!</div>
    }
}
export default HelloWorld

由此看出以上是一个简单的组件,this.state是对状态的一个初始化赋值的概念。它是一个有状态的组件,具有完整的生命周期概念。但项目中不仅仅是只用这种有状态组件,还有其他组件类型。
无状态组件是通过无状态的函数创建的,它是一种只负责展示的纯组件。无状态组件的特点是不需要管理组件状态state,数据直接通过props传入即可,这也符合React单向数据流的思想。
这里可以科普下无状态组件的概念:

无状态组件

无状态组件可以通过减少继承Component而来的生命周期函数而达到性能优化的效果。从本质上来说,无状态组件就是一个单纯的render函数,所以无状态组件的缺点也是显而易见的。因为它没有shouldComponentUpdate生命周期函数,所以每次state更新,它都会重新绘制render函数。

对于无状态组件的函数式生命方法,不仅可以提高代码的可阅读行,还能大大的减少代码量,提高代码的复用率。

以下是我项目中所写的无状态组件。

const ScaleScorePage = (props) => {
    const patientScales = props.patientStatus.get('newScales')
    return (
        <div className={styles.commonDiagnosisWrapper}>
            <div className={styles.commonDiagnosisTitle}>
                <h3>卒中严重程度评估</h3>
            </div>
            {patientScales &&
            <div className={styles.commonDiagnosisInner}>
                <Row>
                    {renderBaseScoreInner(patientScales)}
                </Row>
            </div>
            }
            <div className={styles["text-right"]} style={{display: 'none'}}><Button>查看出院时量表评分</Button></div>
        </div>
    )
}
export default ScaleScorePage

以上代码中props是父组件传递过来的属性。此时就用到了父组件如何向子组件通信,父组件通过props给子组件传递数据。如下示例:

<ScaleScorePage patientStatus={patientStatus}/>

上面的patientStatus就是属性值通过props传递给子组件ScaleScorePage。

思考:如何在这种无状态组件中想用到生命周期的概念呢?这个就要用到React 16.8的新增特性Hook,它可以让你在不编写class的情况下使用state以及其他的React特性。

Hook

最近项目中用到的示例:
主要用到的就是 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'}}>记录时间: 暂无</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的知识点的涵盖面可能有点多,首先可以忽略redux这部分内容,这个可以单独几个篇幅去讲解。如何从父组件向子组件传递值上面已经讲过,下面就是讲解useState.

useState
// 声明一个叫做basePatientDetails的 state 变量,
 const [basePatientDetails, onPatientStatementChange] = useState(false)

声明一个叫做basePatientDetails的 state 变量,初始化值设置为false,并且在onPatientStatementChange方法中改变state变量的值。

useEffect

Effect Hook 可以让你在函数组件中执行副作用操作。如果你熟悉React class的生命周期,你可以把useEffect 看作是componentDidMount , componentDidUpdate和componentWillUnmount这三个函数的组合。

useEffect(() ={ props.getPatientComplaint(patientID) } )     //xxxx
useEffect(() ={ props.getPatientComplaint(patientID) },[] )     

⚠️注意:以上写法是有个箭头函数,然后执行了一个API接口调用。因为它具有生命周期的概念,这样又陷入万恶的循环中,所以解决办法是在结尾加 [].

css样式模块化

另外在样式上,最开始写项目的时候,发现引用的css样式是全局的样式,会经常出现样式覆盖问题。这样对于团队开发是非常不友好的。后来在项目中对css起的名字做了研究,xxx.module.css这样自动对css样式进行模块化管理。只需要在组件引用的时候使用

//如果引用多个样式文件
import styles from '../../css/diagnosis/diagnosis.module.css'
import iStyles from '../../css/infomation.module.css'

使用时候这样用,以下有单个类名以及多个类名示例:

<div className={styles.outer}> 
 <div className={`${styles.inner} ${iStyles.border}`}>
</div> 
解构赋值

const { patientID,patientComplaint } = props
//等价于
const patientID = props.patientID
const patientComplaint = props.patientComplaint

列表 & key

map方法非常实用。


<ul>
  {patientComplaint.map((item,idx)=><li key={item.id}>{item}</li>)}
</ul>

由此map方法使用前提必须是一个数组,参数( currentValue, index, arr )。
currentValue (必须。当前元素的值)
index (可选。当前元素的索引值)
arr (可选。当前元素属于的数组对象)

另外:还会有数据改造的情况(出现于后台字段跟前端所用字段不一致)


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:'无'} {params}</span></Fragment>
}
/**处理数值变化值*/
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) => {
    // 接口数据映射处理
    return data.map((item, index) =>({
        key: index,
        examItem: renderExamTitle(item),
        examResult: handlerExamResult(item),
        maleStd: item.maleStd
   
    }))
}

思考💡:
假设如果后台给的数据是长得这个样子,需要前端页面进行循环处理结构。

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 中的三元运算符

如果在jsx语句中用到if-else 语句进行条件渲染怎么办?可以使用三元运算符:

{
  nodeDetails.isFinal?
    <div>有数据 </div> : <div>暂无结果</div>
}
<div>参考范围 {item.range=== null?'暂无':item.range}</div>

如果只返回条件渲染的一方面,可以使用&&运算符

{
data.checks.length>0 &&<div>显示....</div>
}

补充:
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)

未完待续。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容