美文网首页reactReact
入手react项目三个月的心得( 纯干货 )

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

作者: 不忘初心_6b23 | 来源:发表于2019-05-27 22:00 被阅读0次

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

    未完待续。。。

    相关文章

      网友评论

        本文标题:入手react项目三个月的心得( 纯干货 )

        本文链接:https://www.haomeiwen.com/subject/xppktctx.html