reactReact

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

2019-05-27  本文已影响0人  不忘初心_6b23

本篇文章并不是按照官网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)

未完待续。。。

上一篇 下一篇

猜你喜欢

热点阅读