入手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 
hello world!
} } export default HelloWorld

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

无状态组件

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

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

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

const ScaleScorePage = (props) => {
    const patientScales = props.patientStatus.get('newScales')
    return (
        

卒中严重程度评估

{patientScales &&
{renderBaseScoreInner(patientScales)}
}
) } export default ScaleScorePage

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


上面的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 (
        

主诉

记录时间: 暂无
    {patientComplaint.map((item,idx)=>
  • {item}
  • )}
) } 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'

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

解构赋值

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

列表 & key

map方法非常实用。


    {patientComplaint.map((item,idx)=>
  • {item}
  • )}

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

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


const renderExamTitle = (item) => {
    return {item.examItem||''}{item.examUnit||''}
}
const renderExamResult = (item, params, style1) => {
    return {item.examResult?item.examResult:'无'} {params}
}
/**处理数值变化值*/
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 !


    {Object.keys(options).map((itm, idx) =>
  • {options[itm]}

    {itm}

  • )}
React 中的三元运算符

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

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

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

{
data.checks.length>0 &&
显示....
}

补充:
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项目三个月的心得( 纯干货 ))