react函数组件

2023-10-30

一、函数组件

1、函数组件的创建

函数组件:使用JS的函数(或箭头函数)创建的组件称为函数组件,函数组件有如下约定

  • 函数名称必须以大写字母开头
  • 函数组件必须有返回值,返回JSX表达式
  • 渲染函数组件:用函数名作为组件标签名
  • 组件名称可以是单标签也可以是双标签
export default function Hello(){
    return (
        <div>
            Hello Function Component
        </div>
    )
}

VSCode 中快捷键 rfc 可自动生成。

创建完函数组件,可以将其引入到App.jsx中

import './App.css'
import Hello from './Hello';
function App() {
  return (
    <div>
      <Hello></Hello>
    </div>
  );
}
export default App;

2、函数组件事件处理

注意:函数组件中绑定方法不需要this

export default function Hello() {
    const clickEvent = () => {
        console.log('2');
    }
    const getParams = (params) => {
        console.log(params);
    }
    return (
        <>
            <button onClick={() => {
                console.log('1');
            }}>按钮</button>
            <button onClick={clickEvent}>按钮</button>
            <button onClick={() => getParams('3')}>传参</button>
        </>
    )
}

3、函数组件的Prop

3.1、函数组件的Props

import React from 'react';
import ReactDOM from 'react-dom';
function LoginForm(props){
    return <h1>{props.title}登录</h1>;
}
const template=<LoginForm title='管理员'></LoginForm>
ReactDOM.render(template,document.getElementById('root'));

当然也可以自己在调用函数组件的时候指定其他的,比如下面这个例子输入会员,就会变成会员登录

import React from 'react';
import ReactDOM from 'react-dom';
function LoginForm(props){
    return <h1>{props.title}登录</h1>;
}
const template=<LoginForm title='会员'></LoginForm>
ReactDOM.render(template,document.getElementById('root'));

下面我们再定义一个函数式组件,然后在这里边传递多个参数

import React from 'react';
import ReactDOM from 'react-dom';

function UserInfo(props){
    console.log(props);
    const template=(
        <div>
            <ul>
                <li>姓名:{props.username}</li>
                <li>年龄:{props.age}</li>
                <li>特长:{props.specialty}</li>
            </ul>
        </div>
    );
    return template;
}
const template=(
    <div>
        <UserInfo username={'马保国'} age={56} specialty={'太极'}></UserInfo>
    </div>
);
ReactDOM.render(template,document.getElementById('root'));

显示效果如下所示,我们通过对控制台的观察,会发现props就是传递的JS对象的值

如上给组件赋值除了赋常量外也可以传递变量,如下所示

import React from 'react';
import ReactDOM from 'react-dom';

function UserInfo(props){
    const template=(
        <div>
            <ul>
                <li>姓名:{props.username}</li>
                <li>年龄:{props.age}</li>
                <li>特长:{props.specialty}</li>
            </ul>
        </div>
    );
    return template;
}
const u={
    username:'马保国',
    age:69,
    specialty:'打太极'
};
const template=(
    <div>
        <UserInfo username={u.username} age={u.age} specialty={u.specialty}></UserInfo>
    </div>
);
ReactDOM.render(template,document.getElementById('root'));

其实还有简写方式

import React from 'react';
import ReactDOM from 'react-dom';

function UserInfo(props){
    const template=(
        <div>
            <ul>
                <li>姓名:{props.username}</li>
                <li>年龄:{props.age}</li>
                <li>特长:{props.specialty}</li>
            </ul>
        </div>
    );
    return template;
}
const u={
    username:'马保国',
    age:69,
    specialty:'打太极'
};
const template=(
    <div>
        <UserInfo {...u}></UserInfo>
    </div>
);
ReactDOM.render(template,document.getElementById('root'));

3.2、props默认值

首先,先来完成一个函数组件的默认值案例

import React from 'react';
import ReactDOM from 'react-dom';

function UserInfo(props){
    const template=(
        <div>
            <ul>
                <li>姓名:{props.username}</li>
                <li>年龄:{props.age}</li>
                <li>特长:{props.specialty}</li>
            </ul>
        </div>
    );
    return template;
}
//设置默认值的语法 组件名.defaultProps
UserInfo.defaultProps={
    username:'无名氏',
    age:0,
    specialty:'无特长'
}
const template=(
    <div>
        <UserInfo username='张明理'></UserInfo>
    </div>
);
ReactDOM.render(template,document.getElementById('root'));

这里如果在调用组件的时候赋值,那么默认值就不会生效了,倘若,默认值就会生效。

3.3、props验证器

import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';

function UserInfo(props){
    const template=(
        <div>
            <ul>
                <li>姓名:{props.username}</li>
                <li>年龄:{props.age}</li>
                <li>特长:{props.specialty}</li>
            </ul>
        </div>
    );
    return template;
}
UserInfo.propTypes={
    username:PropTypes.string.isRequired,
    age:PropTypes.number.isRequired,
    specialty:PropTypes.string
}
const template=(
    <div>
        <UserInfo age={'20岁'} specialty='打羽毛球'></UserInfo>
    </div>
);
ReactDOM.render(template,document.getElementById('root'));

4、有状态组件和无状态组件

  • 函数组件又叫做无状态组件,类组件又叫做有状态组件
  • 状态(state)即数据,是组件内部的私有数据,只能在组件内部使用
  • 函数组件没有自己的状态,只负责数据展示
  • 类组件有自己的状态,负责更新UI

二、Hook简介

1、hook的由来和作用

react16.8以后的新特性Hooks函数组件在react16.8以前函数组件只能被动接收外部数据,并且没有自己的生命周期钩子函数,函数内部也没有this可用新特性Hookhook推出的动机主要是因为类组件有一下几个不足

  • 组件之间复用公共逻辑比较麻烦,以前常见的提取组件公共逻辑的方式有高阶组件/renderProps等,但这些方式或多或少都对原有组件的代码组织方式有一定的破坏性
  • 复杂组件变得难以理解(例如相同的逻辑可能要写在不同的生命周期钩子函数里面)
  • 难以理解的class(比如对新手来见,class组件中的this不太好理解)

新特性hook出现之后,函数组件就可以完全替代类组件,但是这并不是说react官方会抛弃类组件,react官方文档中也表明了没有计划会在react中移除class组件。

注意:hook特性只能在函数组件中使用

三、State Hook

1、作用

useState 为函数组件提供了状态(state)

2、基本使用

2.1、使用步骤

  • 导入useState函数
import { useState } from 'react'
  • 调用useState函数,并传入状态的初始值,从useState函数的返回值中,拿到状态和修改状态的方法
const [变量名, 方法名] = useState(数据初始值);
  • 在jsx中展示状态
  • 使用修改状态的方法更新状态

2.2、代码实现

import { useState } from 'react'

export default function Counter() {
    const [count, setCount] = useState(0);
    const decrement = () => {
        setCount(count - 1)
    }
    return (
       <>
         <h1>计数器:{count}</h1>
         <button onClick={decrement}>-1</button>
         <button onClick={() => {setCount(count + 1)}}>+1</button>
        </>
    )
}

注意:修改数据的 set 方法,只需要接收一个新数据作为参数,方法内部会自动用接收到的新数据来覆盖旧数据。

3、函数作为参数

  • 语法
const [变量名, 方法名]=useState(()=>{return '计算之后的初始值'})
  • 语法规则
    • 回调函数return出去的值作为变量名的初始值
    • 回调函数中的逻辑只会在组件初始化的时候执行一次
  • 语法选择
    • 如果初始化一个普通的数据,直接使用useState(初始值)即可
    • 如果要初始化的数据无法直接得到需要通过计算才能获取到,使用useState(()=>{})
  • 案例实现
import {useState} from 'react'
function Counter(props){
  const [count,setCount]=useState(()=>{
    return props.count
  })
  return(
    <>
      <h2>{count}</h2>
      <button onClick={()=>setCount(count+1)}>+</button>
    </>
  )
}
function App() {
  return(
    <>
      <Counter count={10}></Counter>
      <Counter count={20}></Counter>
    </>
  )
}
export default App;

四、 Effect Hook

1、作用

  • 副作用:副作用是相对与主作用而言的,一个函数除了主作用,其他作用都是副作用,对于React组件来说,主作用是根据数据(state/props)渲染UI,除此之外都是副作用
  • 常见的副作用
    • 数据请求Ajax发送
    • 手动修改DOM
    • localStorage操作
  • Effect Hook 可以让你在函数组件中执行副作用操作
import {useState,useEffect} from 'react'

export default function Example() {
  const [count,setCount]=useState(0)
  useEffect(()=>{
      document.title=`You clicked ${count} times`
  })
  return (
    <div>
        <p>You clicked {count} times</p>
        <button onClick={()=>{setCount(count+1)}}>Click Me</button>
    </div>
  )
}

2、useEffect 的参数

import { useEffect } from 'react'
useEffect(() => {}, []);

useEffect 的参数,主要分为两个,第一个固定是一个回调函数,第二个是一个数组(可选)。

参数传递的不同,useEffect 实现的效果也不同。

2.1、没有第2个参数

当 useEffect 只有第一个参数时,其作用就是在模拟 componentDidMount 和 componentDidUpdate 生命周期函数。

也就是说,useEffect 的第一个回调函数,会在组件首次挂载完成执行一次,同时,后续组件每次更新完成时也会执行。

useEffect(() => {
    // ...
})

关键代码如下所示

import {useState,useEffect} from 'react'

export default function Params() {
  const [count,setCount]=useState(0)
  useEffect(()=>{
    console.log('没有第2个参数');
  })
  return (
    <div>
        <h1>{count}</h1>
        <button onClick={()=>setCount(count+1)}>+1</button>
    </div>
  )
}

执行的效果是:组件首次挂载完成执行一次,每次单击按钮会执行一次

2.2、第2个参数是空数组

当 useEffect 的第二个参数是一个空数组是,其作用就是在模拟 componentDidMount 生命周期函数。

也就是说,useEffect 的第一个回调函数,会在组件首次挂载完成执行一次。

useEffect(() => {
    // ...
}, [])

关键代码如下所示

import {useState,useEffect} from 'react'

export default function Params() {
  const [count,setCount]=useState(0)
  useEffect(()=>{
    console.log('没有第2个参数');
  },[])
  return (
    <div>
        <h1>{count}</h1>
        <button onClick={()=>setCount(count+1)}>+1</button>
    </div>
  )
}

执行的效果是:只有在组件首次挂载完成执行一次,后续单击不会执行

2.3、第2个参数是非空数组

当 useEffect 的第二个参数是一个非空数组时,其作用就是在模拟 componentDidMount 生命周期函数,同时还可以模拟 Vue 中 watch 的作用。

也就是说,useEffect 的第一个回调函数,会在组件首次挂载完成执行一次。后续,只要当第二个参数的数组中,任意一条数据发生改变,useEffect 的第一个回调函数又会再次执行。

useEffect(() => {
    // ...
}, [数据1, 数据2, ...])

关键代码如下所示

import {useState,useEffect} from 'react'

export default function Params() {
  const [count,setCount]=useState(0)
  const [name,setName]=useState('张三')
  useEffect(()=>{
    console.log('第2个参数是非空数字');
  },[count])
  return (
    <div>
        <h1>{count}</h1>
        <h1>{name}</h1>
        <button onClick={()=>setCount(count+1)}>+1</button>
        <button onClick={()=>setName('李四')}>更新</button>
    </div>
  )
}

执行的结果是:在组件首次挂载完成执行一次,后续只有在点击+1操作按钮的时候才会调用useEffect的回调函数。单击更新按钮不会触发useEffect回调函数的执行

3、清理副作用

当 useEffect 的第一个参数中,返回了一个函数。那么,返回的这个函数就是在模拟 componentWillUnmount 生命周期函数。

在组件被销毁时,如果有些副作用操作需要被清理,在这里可以写清理副作用的代码。

useEffect(() => {
    return () => {

    }
})

关键代码

import { useEffect } from 'react'

export default function ClearEffect() {
    useEffect(() => {
        let times=setInterval(() => {
            console.log('定时执行操作');
        }, 1000);
        return ()=>{
            clearInterval(times)
        }
    }, [])
    return (
        <div>this is test</div>
    )
}
***************************************************************************************
import ClearEffect from "./ClearEffect"
import { useState } from "react"
export default function App() {
  const [flag,setFlag]=useState(true)
  return (
    <div>
      {flag? <ClearEffect/>:null}
      <button onClick={()=>setFlag(!flag)}>switch</button>
    </div>
  )
}

4、useEffect-网络请求

import axios from 'axios'
import React, { useState, useEffect } from 'react'

export default function User() {
    const [users, setUsers] = useState([])
    const getUsersApi = async () => {
        let result = await axios.get('http://39.106.34.185:8888/user')
        setUsers(result.data.data.list)
    }
    useEffect(() => {
        getUsersApi()
    }, [])
    return (
        <div>
            <table>
                <tr>
                    <td>昵称</td>
                    <td>手机号</td>
                    <td>绑定汽车数量</td>
                    <td>订单数量</td>
                    <td>未缴费订单数量</td>
                    <td>状态</td>
                    <td>创建事件</td>
                    <td>操作</td>
                </tr>
                {
                    users.map(item => <tr key={item.id}>
                        <td>{item.name}</td>
                        <td>{item.tel}</td>
                        <td>{item.carNum}</td>
                        <td>{item.orderNum}</td>
                        <td>{item.orderNum}</td>
                        <td>{item.state==1?'启用':'禁用'}</td>
                        <td>{item.createTime}</td>
                        <td>
                            <span>查看</span>
                            <span>订单详情</span>
                            <span>更多</span>
                        </td>
                    </tr>)
                }
            </table>
        </div>
    )
}

五、 useRef

1、作用

在函数组件中获取DOM元素或者组件对象

2、使用步骤

  • 导入useRef函数
import { useRef } from 'react'
  • 执行useRef函数,返回一个ref对象
function 组件名() {
    const 变量名 = useRef();
}
  • 绑定 ref

找到函数组件中对应的节点,通过 ref 属性将 ref 对象绑定到元素节点身上:

function 组件名() {
    const 变量名 = useRef();
    return (
        <节点 ref={变量名}></节点>
    )
}
  • 获取元素节点

当元素通过 ref 绑定了元素后,就可以通过 ref 对象来获取元素节点了:

function 组件名() {
    const 变量名 = useRef();
    return (
        <节点 ref={变量名} onClick={() => {
            console.log(变量名.current);   // 元素节点    
        }}></节点>
    )
}

3、代码实现

import React,{useRef} from 'react'
import './Ball.css'
export default function Ball() {
  const ballRf=useRef()
  const changeBall=()=>{
    ballRf.current.style.backgroundColor="springgreen"
  }
  return (
    <div>
        <div className="box" ref={ballRf}></div>
        <button onClick={changeBall}>变化</button>
    </div>
  )
}

六、useMemo

1、作用

useMemo的作用类似vue中的计算属性computed,即根据母体数据衍生出新的数据,一旦母体数据发生变化,则useMemo会自动执行

2、基础语法

import { useMemo } from 'react'

const 变量名 = useMemo(() => {
    return 计算得到的数据;
}, [依赖的原数据])

最终,计算得到的数据,就会通过 return 保存到变量身上。

关键代码如下所示

import {useState,useMemo} from 'react'

export default function App() {
  const [fnum,setFnum]=useState(10)
  const [snum,setSnum]=useState(20)
  const sum=useMemo(()=>{
    return fnum+snum
  },[fnum,snum])
  return (
    <div>
      <h1>{sum}</h1>
      <button onClick={()=>setFnum(fnum+2)}>fnum+2</button>
      <button onClick={()=>setSnum(snum+3)}>snum+3</button>
    </div>
  )
}

3、使用hook实现购物车功能

import axios from 'axios'
import React, { useState, useEffect,useMemo } from 'react'
import './ShopCartList.css'

export default function ShopCartList() {
    const [list, setList] = useState([])
    const fetchShopCartData = async () => {
        const result = await 
        axios.get('http://www.zhaijizhe.cn:3001/shopcart/getShopcartData')
        console.log(result.data);
        setList(result.data.data)
    }
    const total=useMemo(()=>{
        return list.filter(item=>item.checked).reduce((pre,cur)=>pre+cur.price*cur.num,0)
    },[list])
    const changeNum=async(_id,n)=>{
       let result=await 
       axios.post('http://www.zhaijizhe.cn:3001/shopcart/changeNum',{_id,n})
       if(result.data.code){
         fetchShopCartData()
       }
    }
    const checkItem=async(_id)=>{
      let result=await 
      axios.get('http://www.zhaijizhe.cn:3001/shopcart/checkProducts',{params:{_id}})
      if(result.data.code){
        fetchShopCartData()
      }
    }
    const changeNum1=(_id,index,n)=>{
        list[index].num=n
        setList(()=>{
            return[
                ...list
            ]
        })
    }
    const submitChangeNum=async(_id,n)=>{
        let result=await 
            axios.post('http://www.zhaijizhe.cn:3001/shopcart/changeNumByInput',{_id,n})
        if(result.data.code){
          fetchShopCartData()
        }
    }

    useEffect(() => {
        fetchShopCartData()   
    }, [])
    
    return (
        <div>
            <h1>购物车</h1>
            <table>
                <thead>
                    <tr>
                        <th>序号</th>
                        <th>名称</th>
                        <th>价格</th>
                        <th>数量</th>
                        <th>小计</th>
                    </tr>
                </thead>
                <tbody>
                    {
                        list.map((item,index)=><tr key={item._id}>
                            <td>
                                <input type='checkbox'
                                onChange={()=>checkItem(item._id)} 
                                checked={item.checked}/>
                            </td>
                            <td>{item.name}</td>
                            <td>{item.price}</td>
                            <td>
                                <button onClick={()=>changeNum(item._id,-1)}>-</button>
                                 <input type="text" value= {item.num} 
                                     onChange={(e)=>
                                        {changeNum1(item._id,index,e.target.value)}} 
                                     onBlur={(e)=>
                                        {submitChangeNum(item._id,e.target.value)}}/>
                                <button onClick={()=>changeNum(item._id,1)}>+</button>
                            </td>
                            <td>{item.price*item.num}</td>
                        </tr>)
                    }
                    <tr>
                        <td colSpan={5} style={{textAlign:'right'}}>
                            总计:{total}
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    )
}

七、echarts

1、React引入echarts

  • 安装echarts
yarn add echarts 
  • 自定义组件
import React,{useEffect} from 'react'
import * as echarts from 'echarts';
export default function ChartBar(props) {
  const {optionsData = null, id = 'default-id', width = 600, height = 200,title="echart演示",seriesName} = props;
  useEffect(()=>{
        let xData=optionsData.xdata
        let yData=optionsData.ydata
        const options={
          title: {
            text:title
          },
          tooltip: {},
          xAxis: {
            data: xData
          },
          yAxis: {},
          series: [
            {
              name: seriesName,
              type: 'bar',
              data: yData
            }
          ]
        }
        const chart = echarts.init(document.getElementById(id));
        chart.setOption(options);
  },['optionsData'])

  return (
    <div id={id} style={{width: width, height: height}}>222</div>
  ) 
}
  • 引入
import React,{useState} from 'react'
import ChartBar from './views/ChartBar'

export default function App() {
  const [echarts,setEcharts]=useState({
    xdata:['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
    ydata: [5, 20, 36, 10, 10, 20]})
  return (
    <div>
      <ChartBar 
        id="chart-bar"
        optionsData={echarts}
        title={"echart演示"}
        seriesName={"销量"}
        width={880}
        height={300}></ChartBar>
    </div>
  )
}

2、柱状图的配置

2.1、常见效果设置

  • 最大值、最小值、平均值标记设置
 series: [
            {
              name: seriesName,
              type: 'bar',
              data: yData,
              markPoint:{
                data:[
                  {
                    type:'max',name:'最大值'
                  },
                  {
                    type:'min',name:'最小值'
                  }
                ]
              },
              markLine:{
                data:[
                  {
                    type:'average',name:'平均值'
                  }
                ]
              }
            }
          ]
  • 图形上的文本标签的设置
 series: [
            {
              label:{
                show:true,
                rotate:65,
                color:'#f00',
                backgroundColor:'#ff0',
                position:'top'
              }
            }
          ]
  • 图形的样式设置
 series: [
      {
         itemStyle:{
            color:'#f00'
         }
       }
 ]
  • 更改柱条的宽度
 series: [
      {
         barWidth:15
       }
 ]
  • 更改x轴和y轴的角色
const options={
    xAxis: {},
    yAxis: { data: xData},
}

2.2、title的相关配置

属性 类型 含义
text string 主标题文本
link string 主标题超链接
textStyle object color:主标题文字的颜色。
fontStyle:主标题的风格
fontWeight:主标题字体的粗细
backgroundColor Color 背景色
borderColor Color 边框颜色
borderRadius number|Array 圆角半径
const options={
          title: {
            text:title,
            link:'http://www.zhaijizhe.cn',
            textStyle:{
              color:'#00ffff',
              fontStyle:'lighter',
              fontSize:38
            },
            backgroundColor:'#ff0',
            borderColor:'#000',
            borderRadius:15
          }
}

2.3、tooltip的相关配置

tooltip:提示框组件,用于配置鼠标滑过或点击图标时的显示框

  • 触发类型:trigger
  • 触发时机:triggerOn
  • 格式化:formatter
const options={
    tooltip:{
        show:true,
        trigger:'axis',
        triggerOn:'click',
        formatter:`{b}的销量是{c}`
     }  
}

2.4、toolbox的相关配置

toolbox:ECharts提供的工具栏:内置有导出图片,数据视图,动态类型切换,数据区域缩放,重置五个工具

const options={
   toolbox:{
      feature:{
          saveAsImage:{},
          restore:{},
          dataView:{
            show:true
          },
          dataZoom:{},
          magicType:{
             type:['bar','line']
          }
       }
    } 
}

2.5、legend的相关配置

legend:图例,用于筛选系列,需要和series配置使用

  • legend中的data是一个数组
  • legend中的data的值需要和series数组中某组数据的name值一致。
import React,{useEffect} from 'react'
import * as echarts from 'echarts';
export default function ChartBar(props) {
  const {optionsData = null, id = 'default-id', width = 600, height = 200,title="echart演示"} = props;
  useEffect(()=>{
        let xData=optionsData.xdata
        let y1Data=optionsData.y1data
        let y2Data=optionsData.y2data
        let y3Data=optionsData.y3data
        const options={
          title: {
            text:title
          },
          tooltip: {},
          xAxis: {
            data: xData
          },
          yAxis: {},
          legend: {
            data: ['1月份销量', '2月份销量', '3月份销量']
          },
          series: [
            {
              name: "1月份销量",
              type: 'bar',
              data: y1Data
            },
            {
                name: "2月份销量",
                type: 'bar',
                data: y2Data
            },
            {
                name: "3月份销量",
                type: 'bar',
                data: y3Data
            }
          ]
        }
        const chart = echarts.init(document.getElementById(id));
        chart.setOption(options);
  },['optionsData'])

  return (
    <div id={id} style={{width: width, height: height}}>222</div>
  ) 
}
import React,{useState} from 'react'
import ChartBar from './views/ChartBar1'

export default function App() {
  const [echarts,setEcharts]=useState({
    xdata:['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
    y1data: [5, 20, 36, 10, 10, 20],
    y2data: [3, 10, 26, 5, 12, 22],
    y3data: [2, 12, 6, 15, 22, 52]
  }
  )
  return (
    <div>
      <ChartBar 
        id="chart-bar"
        optionsData={echarts}
        title={"echart演示"}
        width={880}
        height={300}></ChartBar>
    </div>
  )
}

3、折线图的配置

2.1、基本配置

import React,{useEffect} from 'react'
import * as echarts from 'echarts';
export default function ChartBar(props) {
  const {optionsData = null, id = 'default-id', width = 600, height = 200,title="echart演示",seriesName} = props;
  useEffect(()=>{
        let xData=optionsData.xdata
        let yData=optionsData.ydata
        const options={
          title:{
            text:title
          },
          xAxis: {
            data: xData
          },
          yAxis: { },
          series: [
            {
              name: seriesName,
              type: 'line',
              data: yData,
            }
          ]
        }
        const chart = echarts.init(document.getElementById(id));
        chart.setOption(options);
  },['optionsData'])

  return (
    <div id={id} style={{width: width, height: height}}>222</div>
  ) 
}
import React,{useState} from 'react'
import ChartBar from './views/ChartBar'

export default function App() {
  const [echarts,setEcharts]=useState({
    xdata:['1月', '2月', '3月', '4月', '5月', '6月','7月','8月','9月','10月','11月','12月'],
    ydata: [5, 20, 36, 10, 10, 20,89,100,22,56,78,99]})
  return (
    <div>
      <ChartBar 
        id="chart-bar"
        optionsData={echarts}
        title={"某培训机构2021年全年招生"}
        seriesName={"招生量"}
        width={880}
        height={600}></ChartBar>
    </div>
  )
}

2.2、常见效果设置

  • 最大、最小、平均值标记、设置标注区域
const options={
          title:{
            text:title
          },
          xAxis: {
            data: xData
          },
          yAxis: { },
          series: [
            {
              name: seriesName,
              type: 'line',
              data: yData,
              markPoint:{
                data:[
                  {
                    type:'max'
                  },
                  {
                    type:'min'
                  }
                ]
              },
              markLine:{
                data:[
                  {
                    type:'average'
                  }
                ]
              }
            }
          ]
        }

const options={
          title:{
            text:title
          },
          xAxis: {
            data: xData
          },
          yAxis: { },
          series: [
            {
              name: seriesName,
              type: 'line',
              data: yData,
              markPoint:{
                data:[
                  {
                    type:'max'
                  },
                  {
                    type:'min'
                  }
                ]
              },
              markLine:{
                data:[
                  {
                    type:'average'
                  }
                ]
              },
              markArea:{
                data:[
                  [
                    {
                      xAxis:'1月'
                    },
                    {
                      xAxis:'2月'
                    }
                  ],
                  [
                    {
                      xAxis:'8月'
                    },
                    {
                      xAxis:'9月'
                    }
                  ]
                ]
              }
            }
          ]
        }

  • 线条控制:平滑、风格
 const options={
          title:{
            text:title
          },
          xAxis: {
            data: xData
          },
          yAxis: { },
          series: [
            {
              smooth:true,
              lineStyle:{
                color:'green',
                type:'dotted'
              }
          ]
        }
  • 填充风格
 const options={
          title:{
            text:title
          },
          xAxis: {
            data: xData
          },
          yAxis: { },
          series: [
            {
               areaStyle:{
                color:'skyblue'
            }
          ]
        }

2.3 多线设置

import React,{useEffect} from 'react'
import * as echarts from 'echarts';
export default function ChartBar(props) {
  const {optionsData = null, id = 'default-id', width = 600, height = 200,title="echart演示",seriesName} = props;
  useEffect(()=>{
        let xData=optionsData.xdata
        let yData=optionsData.ydata
        let y2Data=optionsData.y2data
        const options={
          title:{
            text:title
          },
          xAxis: {
            data: xData
          },
          yAxis: { },
          series: [
            {
              name: seriesName,
              type: 'line',
              data: yData,
            },
            {
              name: seriesName,
              type: 'line',
              data: y2Data,
            }
          ]
        }
        const chart = echarts.init(document.getElementById(id));
        chart.setOption(options);
  },['optionsData'])

  return (
    <div id={id} style={{width: width, height: height}}>222</div>
  ) 
}
import React,{useState} from 'react'
import ChartBar from './views/ChartBar'

export default function App() {
  const [echarts,setEcharts]=useState({
    xdata:['1月', '2月', '3月', '4月', '5月', '6月','7月','8月','9月','10月','11月','12月'],
    ydata: [5, 20, 36, 10, 10, 20,89,100,22,56,78,99],
    y2data: [15, 25, 46, 20, 20, 40,99,100,32,46,28,19]
    })
  return (
    <div>
      <ChartBar 
        id="chart-bar"
        optionsData={echarts}
        title={"某培训机构2021年全年招生"}
        seriesName={"招生量"}
        width={880}
        height={600}></ChartBar>
    </div>
  )
}

4、饼形图的配置

4.1、基本配置

import React,{useEffect} from 'react'
import * as echarts from 'echarts';
export default function ChartBar(props) {
  const {pieData = null, id = 'default-id', width = 600, height = 200,title="echart演示"} = props;
  useEffect(()=>{
        const options={
          title:{
            text:title
          },
          series: [
            {
              type: 'pie',
              data: pieData,
            }
          ]
        }
        const chart = echarts.init(document.getElementById(id));
        chart.setOption(options);
  },['optionsData'])

  return (
    <div id={id} style={{width: width, height: height}}>222</div>
  ) 
}

import React, { useState } from 'react'
import ChartBar from './views/ChartBar'

export default function App() {
  const [echarts, setEcharts] = useState(
    [
      { name:"吃饭",value: 1321},
      { name:"旅游",value:123},
      {name:"交通",value:671},
      {name:"购买书籍",value:2345},
      {name:"买衣服",value:67}
    ])
  return (
    <div>
      <ChartBar
        id="chart-bar"
        pieData={echarts}
        title={"全年消费情况"}
        width={880}
        height={600}></ChartBar>
    </div>
  )
}

4.2、常见效果设置

const options={
          title:{
            text:title
          },
          series: [
            {
              type: 'pie',
              data: pieData,
              label:{
                show:true,
                formatter:function(arg){
                  return arg.name+'部分消费了'+arg.value+'元\n'+arg.percent+'%'
                }
              },
              //radius:['60%','80%'],
              roseType:'radius',
              selectedMode:'single'
            }
          ]
        }

八、React.memo和useCallback

1、React.memo

React.memo 可以用来缓存组件。

在 React 中,默认情况下,父组件更新时,无论子组件内部是否改变,子组件也会更新。

但是,从性能考虑,我们希望的是:父组件更新时,如果子组件内部(state 和 props)没有发生改变,子组件不用更新。

解决方法,就是用 React.memo 将子组件缓存起来。

import {useState} from 'react'
import HookChild from './HookChild'

export default function HookParent() {
  console.log('父组件');
  const [count,setCount]=useState(0)
  return (
    <div>
        <h1>父组件:{count}</h1>
        <button onClick={()=>setCount(count+1)}>+1</button>
        <HookChild></HookChild>
    </div>
  )
}

import React from 'react'

function HookChild() {
    console.log('子组件');
    return (
        <h2>子组件</h2>
    )
}

export default React.memo(HookChild);

2、useCallback

useCallback 可以用来缓存函数。

2.1、基础语法

import { useCallback } from 'react';

const 变量名 = useCallback(缓存的函数, [])

2.2、应用场景

通常,我们为了减少子组件不必要的更新,会使用 React.memo() 来缓存子组件的状态。

但是,如果父组件传递了函数给子组件,那么,每次父组件更新时,函数都会重新创建。子组件中的 React.memo() 就会判定为父组件传递的内容发生了改变,那么 React.memo() 就不会缓存当前子组件的状态。

因此,为了解决函数的问题,我们需要保存函数的状态,让父组件更新时函数能够缓存下来,因此我们需要使用 useCallback 将传递的子组件的函数状态缓存起来。

import { useCallback, useState } from "react";
import HookChild from "./HookChild";

export default function HookFather() {
    console.log('父组件');
    const [count, setCount] = useState(0);

    const sayHello = () => {
        console.log('hello');
    }
    // 缓存函数状态
    const cbSayHello = useCallback(sayHello, []);

    return (
        <>
            <h1>父组件:{count}</h1>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <HookChild sayHello={cbSayHello}></HookChild>
        </>
    )
}
import React from 'react'
function HookChild({sayHello}) {
  console.log('子组件');
  return (
    <div>
        <h2>子组件</h2>
    </div>
  )
}
export default React.memo(HookChild)

九、自定义hook

自定义hook提取函数组件公共逻辑

  • 自定义hook的作用在于提取公共逻辑,所以一般不会返回一个JSX对象,而是会根据需要返回特定的数据或者方法
  • 自定义hook必须要以use开头

假设现在有Test1和Test2两个函数组件,他们有一些公共逻辑需要提取,比如都要从后台获取一个列表数据,然后用户界面的渲染,则现在可以编写一个自定义hook来提取这部分公共逻辑,以避免重复写代码

import {useState,useEffect} from 'react'
export default function useData(){
    const [list,setList] = useState([]);
 useEffect(()=>{setTimeout(()=>{            
        const list = [1,2,3]            
        setList(list);        
    },200);},[]);
    return {list,}}
//Test1
import useData from '...'
function Test1(){
    const {list} = useData();
    return 
    div>
        {...用list渲染JSX}
    </div>
}
//Test2类似
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

react函数组件 的相关文章

随机推荐

  • 软件实现数字滤波

    数字滤波器 说白了 就是多次采样求平均值的一个过程 精确一点的 就是再顺序排列 去掉首位再求平均值 哈哈 这就是数字滤波器的原理 就是求平均数 单片机数字滤波的算法 单片机主要作用是控制外围的器件 并实现一定的通信和数据处理 但在某些特定场
  • 计算机软件基础实验,计算机软件基础实验

    计算机软件基础实验 由会员分享 可在线阅读 更多相关 计算机软件基础实验 18页珍藏版 请在人人文库网上搜索 1 北京联合大学 实验报告 课程 项目 名称 计算机软件技术基础实 验一 顺序表 学 院 自动化 专 业 信息处理 与智能技术 班
  • matlab yolov2对整个测试集的图片进行预测的代码

    这个是matlab代码对yolov2生成的模型进行测试的代码 他会在图片生成boundingbox close all clear clc gpuDevice 1 load standard cell2 detector yolov2 06
  • 深度学习检测小目标常用方法

    点击上方 小白学视觉 选择加 星标 或 置顶 重磅干货 第一时间送达 作者丨船长 知乎 来源丨https zhuanlan zhihu com p 83220498 引言 在深度学习目标检测中 特别是人脸检测中 小目标 小人脸的检测由于分辨
  • 哲理故事300篇 中

    哲理故事300篇 上 http blog csdn net andylin02 archive 2006 08 23 1109314 aspx 哲理故事300篇 下 http blog csdn net andylin02 archive
  • 汽配企业想上MES管理系统,需要具备哪些条件

    随着全球汽车行业的快速发展 汽配行业也面临着日益激烈的竞争和不断变化的市场环境 为了应对这种挑战 许多汽配企业开始考虑引入制造执行系统 MES 来提高生产效率和管理水平 然而 在实施MES管理系统解决方案之前 汽配企业需要具备一定的条件 以
  • 整理 mac 安装php扩展mcrypt

    这个问题是遇到多次了 不想再被坑了 首先使mcrypt软件能够运行 然后安装php扩展模块 并在php ini配置 这里注意的是mcrypt软件依赖libmcrypt和mhash两个库 所以安装配置顺序从右至左 下载安装mcrypt 1 先
  • Java Solr HTTPClient一般请求流程代码编写

    import com alibaba fastjson JSONObject import com digipower common page PageData 查询的策略模式 author zzg public interface Sea
  • 整理 firefox 和IE系列的相关差别,已备后用!

    一 IE与FireFox的js和css png透明 AlphaImageLoaderfilter progid DXImageTransform Microsoft AlphaImageLoader enabled bEnabled siz
  • STC32G资料及入门介绍

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 STC32G资料及入门介绍 前言 一 资料准备 二 工程介绍 1 文件架构 总结 前言 提示 这里可以添加本文要记录的大概内容 STC32G是STC新推出的32位单片机 也就
  • 2、OpenCV加载、显示、保存图像

    OpenCV加载 显示 保存图像 一 OpenCV加载图像 二 判断图像是否加载成功 三 窗体显示图片 四 保存图像 五 完整代码示例 六 其它关于图像保存的代码例子 七 致谢 一 OpenCV加载图像 1 所用函数原型 Mat cv im
  • CAN光纤转换器 CAN光端机在久远消防主机JB-TB-JF999-H上的应用

    火灾报警主机联网问题一直是各消防项目中的难点 特别是管廊等长距离通讯中 如何保证通讯信号长期稳定可靠的运行是需要工程重点解决的问题 而LCAN FOBR系列环网冗余式CAN光纤转换器提供二路光通道和一路CAN通道 实现CAN与光纤之间的双向
  • “文明上网”

    接下来 让我们通过一些司法案例来学习如何做到 文明上网 安全上网 吧 案例一 不听劝告沉溺网络 步步深陷堕入深渊 十四岁的韩某从小就迷恋网络 家人越是劝告越是不听 到后来甚至发展到通宵到网吧打游戏 2018年3月 因无钱上网玩游戏 韩某先后
  • ajax设置滚轮效果,用 jQuery 实现页面滚动(Scroll)效果的完美方法

    以前很多博主都写过 转载过用 jQuery 实现页面滚动 Scroll 效果的方法 但目前搜来的方法大都在 Opera 下有个小 Bug 直接用跳的而且画面闪烁 今天 超级低调的高手 Willin 共享了一种完美方法解决 jQuery 实现
  • 经典进程同步问题(三)——读者写者问题

    目录 一 问题描述 二 解题思路 2 1 读者优先算法 2 2 写者优先算法 2 3 读写公平 三 源码实现 3 1 读者优先 3 2 写者优先 3 3 读写平等 一 问题描述 一个数据问价或记录可以被多个进程共享 我们把只读该文件的进程称
  • 集成学习算法:Bagging和随机森林

    学习目标 知道Bagging集成原理 知道随机森林构造过程 知道RandomForestClassifier的使用 了解baggind集成的优点 1 Bagging集成原理 目标 把下面的圈和方块进行分类 实现过程 1 采样不同数据集 2
  • Wireshark抓包——ICMP协议分析

    内容 使用Wireshark抓包 分析较简单的数据包 环境 Windows 7 Wireshark ping是用来测试网络连通性的命令 一旦发出ping命令 主机会发出连续的测试数据包到网络中 在通常的情况下 主机会收到回应数据包 ping
  • 【Linux-GNU编译器套件(gcc/g++/gfortran)离线编译安装】

    文章目录 Linux centos7 9系统GNU编译器套件 gcc g gfortran 离线编译安装 一 GNU编译器套件定义 二 GNU GCC编译环境说明 三 GNU GCC编译安装 3 1 依赖软件包安装 3 2 gcc 7 5版
  • Hexo博文发布管理工具分享出来啦

    从此刻起 小白也能搭建自己的博客 说些什么呢 之前为朋友写的一个Hexo博客发布与管理工具 只需要点点鼠标即可实现对Hexo博文的管理 从此告别各种难记的cmd命令 赠人玫瑰 手有余香 实现功能 创建博文 修改名称 删除文章 复制 粘贴 剪
  • react函数组件

    一 函数组件 1 函数组件的创建 函数组件 使用JS的函数 或箭头函数 创建的组件称为函数组件 函数组件有如下约定 函数名称必须以大写字母开头 函数组件必须有返回值 返回JSX表达式 渲染函数组件 用函数名作为组件标签名 组件名称可以是单标