当前位置: 首页 > article >正文

千峰React:组件与逻辑封装(上)

UI组件库及antd安装

UI组件库就是把页面的组件写好了,用的时候直接调用好了

进行一个安装的动作:

总之就是搭积木,可以调用里面写好的组件库拼接,也可以结合使用

antd布局和导航组件

组件总览 - Ant Design

这是通用部分

在用的时候可以去掉基础样式,其中一个方法就是用antd design里面自带的去基础样式,但是视频的方法是旧版的

制造间隙

使用ant design的响应式布局

import { Row, Col, BackTop } from 'antd'
const col = {
  background: 'red',
}
function App() {
  return (
    <div>
      <Row gutter={[10,10]}>//设置水平、竖直间距
        <Col xs={12} md={8}>//设置响应尺寸
          <div style={col}>aaaaa</div>
        </Col>
        <Col xs={12} md={8}>
          <div style={col}>bbbbb</div>
        </Col>
        <Col xs={12} md={8}>
          <div style={col}>ccccc</div>
        </Col>
      </Row>
    </div>
  )
}

export default App

小分辨率的时候一行排两个

打分辨率的时候一行排三个

也可以获取ant design的源码


import { Row, Col, Layout } from 'antd'
import 'antd/dist/reset.css'
const { Header, Footer, Sider, Content } = Layout

const colStyle = {
  background: 'red'
}
const headerStyle = {
  textAlign: 'center',
  color: '#fff',
  height: 64,
  paddingInline: 50,
  lineHeight: '64px',
  backgroundColor: '#7dbcea',
};
const contentStyle = {
  textAlign: 'center',
  minHeight: 120,
  lineHeight: '120px',
  color: '#fff',
  backgroundColor: '#108ee9',
};
const siderStyle = {
  textAlign: 'center',
  lineHeight: '120px',
  color: '#fff',
  backgroundColor: '#3ba0e9',
};
const footerStyle = {
  textAlign: 'center',
  color: '#fff',
  backgroundColor: '#7dbcea',
};

function App() {
  return (
    <div>
      hello App
      <Row gutter={[10, 10]}>
        <Col xs={12} md={8}><div style={colStyle}>aaaaaa</div></Col>
        <Col xs={12} md={8}><div style={colStyle}>bbbbbb</div></Col>
        <Col xs={12} md={8}><div style={colStyle}>cccccc</div></Col>
      </Row>
      <Layout>
        <Sider style={siderStyle}>Sider</Sider>
        <Layout>
          <Header style={headerStyle}>Header</Header>
          <Content style={contentStyle}>Content</Content>
          <Footer style={footerStyle}>Footer</Footer>
        </Layout>
      </Layout>
    </div> 
  )
}
export default App

六月份学长又说这个不学,我们继续跳

直接学后面的实践

手写antd组件

按钮组件

评分组件

全局提示组件

六月份学长说这一块都别学了

自定义Hook

意思就是自己写一个Hook

写一个获取鼠标定位的hook

import { func } from 'prop-types'
import { useEffect, useState } from 'react'
function useMouse() {
  const [state, setState] = useState({
    pageX: NaN,
    pageY: NaN,
  })
  useEffect(() => {
    function move(e) {
      setState({
        pageX: e.pageX,
        pageY: e.pageY,
      })
    }
    document.addEventListener('mousemove', move)
    return () => {
      document.removeEventListener('mousemove', move)
    }
  }, [])
  return state
}

function App() {
  const mouse = useMouse()
  return (
    <div>
      {mouse.pageX},
      {mouse.pageY}
    </div>
  )
}

export default App

其实这些自定义hooks也被别人写好了,比如ahooks和react-use

下载ahooks
ahooks暂时不支持raect19,所以需要降版本

npm install ahooks//下载ahooks
import { useMouse } from 'ahooks'
function App() {
  const mouse = useMouse()
  return (
    <div>
      {mouse.pageX},{mouse.pageY}
    </div>
  )
}
export default App

ahooks写的功能比我们的更完善,比如clientX,是相对于可视区的x位移

实际开发一般都用人家的ahooks

ahooks处理ajax请求

import { useRequest } from 'ahooks'
import axios from 'axios'
async function getData() {
  const res = await axios.get('/cartData.json')
  console.log('Response:', res.data) // 检查返回的数据
  return res.data.list
}

function App() {
    const { data, error, loading } = useRequest(getData)
     if (error) {
       return <div>{error.message}</div>
     }
     if (loading) {
       return <div>loading...</div>
     }

  return (
    <div>
    {}
    </div>
  )
}
export default App

可以从netWork看见axios的网络请求

在这里致谢蚊子咬学长和六月份学长

function App() {
    const { data, error, loading } = useRequest(getData)
     if (error) {
       return <div>{error.message}</div>
     }
     if (loading) {
       return <div>loading...</div>
     }

  return (
    <div>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  )
}
export default App

如果网速比较慢还可以看见loading效果

如果访问的地址出错了会出现报错信息

点击的时候才加载获取数据

onSuccess获取响应成功的结果:

 const { data, error, loading ,run} = useRequest(getData, {
        manual: true,
        onSuccess(res) {
            console.log(res)
        }
    })

把响应成功的结果渲染到data里

import { useRequest } from 'ahooks'
import axios from 'axios'

import { useState } from 'react'
async function getData() {
  const res = await axios.get('/cartData.json')
  console.log('Response:', res.data) // 检查返回的数据
  return res.data.list
}

function App() {
  const [data, setData] = useState([])
  const { error, loading, run } = useRequest(getData, {
    manual: true,
    onSuccess(res) {
      setData(res)
    },
  })
  if (error) {
    return <div>{error.message}</div>
  }
  if (loading) {
    return <div>loading...</div>
  }
  return (
    <div>
      <button onClick={() => run()}>点击</button>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  )
}
export default App

import { useRequest } from 'ahooks'
import axios from 'axios'

import { useState } from 'react'
async function getData() {
  const res = await axios.get('/cartData.json')
  console.log('Response:', res.data) // 检查返回的数据
  return res.data.list
}

function App() {
  const [data, setData] = useState([])
    const { error, loading, run, refresh } = useRequest(getData, {
      //refresh保留上次ajax的行为
    manual: true,
        onSuccess(res, params) {
        console.log(params)
            setData(res)
    },
  })
  if (error) {
    return <div>{error.message}</div>
  }
  if (loading) {
    return <div>loading...</div>
  }
  return (
    <div>
      <button onClick={() => run('run了一次')}>点击</button>
      <button onClick={() => refresh('refrash了一次')}>刷新</button>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  )
}
export default App

上次执行run会log'run了一次',此时再刷新,会记录上次ajax的结果

refresh:重新执行上一次的请求(包括相同的参数)。

还可以实验mutate修改数据

import { useRequest } from 'ahooks'
import axios from 'axios'

import { useState } from 'react'
async function getData() {
  const res = await axios.get('/cartData.json')
  console.log('Response:', res.data) // 检查返回的数据
  return res.data.list
}

function App() {
  const {data ,error, loading, mutate } = useRequest(getData)
  if (error) {
    return <div>{error.message}</div>
  }
  if (loading) {
    return <div>loading...</div>
  }
  return (
    <div>
      <button onClick={() => mutate([{ 'id': 1, 'name': '榴莲' }])}>点击修改数据</button>
      <ul>
        {data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  )
}
export default App

之前写的聊天室切换功能,因为加载时间不同,最后是用useEffect解决的,但是比较麻烦,需要新变量,每次还要做判断

而aHooks的useRequest已经做好内部的清理工作了

import { useRequest } from 'ahooks'
import { useState, useEffect } from 'react'

function fetchChat(title) {
  const delay = title === '电磁场与电磁波' ? 2000 : 1000
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve([
        { id: 1, text: title + '1' },
        { id: 2, text: title + '2' },
        { id: 3, text: title + '3' },
      ])
    }, delay)
  })
}

function Chat({ title }) {
  const { data, error, loading } = useRequest(() => fetchChat(title), {
       refreshDeps:[title]//一旦title改变,重新发起ajax请求
     })
     if (error) {
       return <div>{error.message}</div>
     }
     if (loading) {
       return <div>loading...</div>
     }
 
  return (
    <div>
      {data.map((item) => {
        return <li key={item.id}>{item.text}</li>
      })}
    </div>
  )
}

function App() {
  const [show, setShow] = useState(true)
  const [title, setTitle] = useState('电磁场与电磁波')
  const handleClick = () => {
    setShow(false)
  }
  const handleChange = (e) => {
    setTitle(e.target.value)
  }
  return (
    <div>
      <button onClick={handleClick}>点我退出课堂</button>
      <select value={title} onChange={handleChange}>
        <option value='电磁场与电磁波'>电磁场与电磁波</option>
        <option value='半导体物理'>半导体物理</option>
      </select>
      {show && <Chat title={title} />}
    </div>
  )
}
export default App

ahooks处理请求的高级用法

轮询

import { useRequest } from 'ahooks'
import axios from 'axios'

async function getData() {
  const res = await axios.get('/cartData.json')
  return res.data.list.sort(() => Math.random() - 0.5)
}

function App() {
    const { data, error, loading } = useRequest(getData, {
      pollingInterval: 3000,//轮询获取数据,3秒一次
    })
  if (error) {
    return <div>{error.message}</div>
  }
  if (loading) {
    return <div>loading...</div>
  }
  return (
    <div>
      <ul>
        {data&&data.map((item) => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  )
}
export default App

三秒一次请求

可以防止频闪,具体来说就说加入

     loadingDelay: 1000

这行语句,页面渲染的时间如果不在1s内,就会显示加载界面:loading

如果渲染时间在1s内,就不会显示loading,优化页面

不加防抖,每次点击按钮都会获取数据

import { useRequest } from 'ahooks'
import axios from 'axios'

async function getData() {
  const res = await axios.get('/cartData.json')
  return res.data.list.sort(() => Math.random() - 0.5)
}

function App() {
  const {data, run, error, loading } = useRequest(getData, {
      manual: true,
      onSuccess(ret) {
          console.log(ret)
          
      }
  })
  if (error) {
    return <div>{error.message}</div>
  }
  if (loading) {
    return <div>loading...</div>
  }
  return (
      <div>
          <button onClick={run}>点击</button>
      <ul>{data && data.map((item) => <li key={item.id}>{item.name}</li>)}</ul>
    </div>
  )
}
export default App

加上防抖以后只会执行最后一次的效果

const { data, run, error, loading } = useRequest(getData, {
    manual: true,
    debounceWait: 300,
    onSuccess(ret) {
      console.log(ret)
    },
  })

除了防抖,还有节流,节流是降低触发频率:

import { useRequest } from 'ahooks'
import axios from 'axios'

async function getData() {
  const res = await axios.get('/cartData.json')
  return res.data.list.sort(() => Math.random() - 0.5)
}

function App() {
  const { data, run, error, loading } = useRequest(getData, {
    manual: true,
    throttleWait: 1000,
   // debounceWait: 300,
    onSuccess(ret) {
      console.log(ret)
    },
  })
  if (error) {
    return <div>{error.message}</div>
  }
  if (loading) {
    return <div>loading...</div>
  }
  return (
      <div>
          <button onClick={run}>点击</button>
      <ul>{data && data.map((item) => <li key={item.id}>{item.name}</li>)}</ul>
    </div>
  )
}
export default App

触发太多次,都按照设定的时间1秒一次,一秒内一次也没有触发就不执行

离开窗口再回到窗口会再次发起请求

从缓存里取数据,不用重新加载

ahooks处理业务场景

import { useHistoryTravel } from "ahooks"; 

function App() {
    const { value='', setValue, backLength, forwardLength, back, forward } =
      useHistoryTravel()
    return (
      <div>
        <input type='text' value={value} onChange={(e)=>setValue(e.target.value)}/>
        <button disabled={backLength <= 0} onClick={back}>后退</button>
        <button disabled={forwardLength<= 0} onClick={forward}>前进</button>
        <br />
        {value}
      </div>
    )
}
export default App

可以控制e.target.value控制输入框的内容到页面渲染上

import { useDynamicList } from "ahooks"; 
import { MinusCircleOutlined ,PauseCircleOutlined} from "@ant-design/icons";

function App() {
    const { list, remove,insert, replace } = useDynamicList(['David', 'Jack']);
  return (
    <div>
      {list.map((item, index) => {
        return (
          <div key={index}>
            <input type="text" value={item} onChange={ (e)=>replace(index,e.target.value)} />
            <MinusCircleOutlined />
            <PauseCircleOutlined/>
        </div>
       )
      })}
      <br />
        <ul>
          {list.map((item, index) => (
            <li key={index}>
              {item}
            </li>
          ))}
       </ul>
      </div>
    )
}
export default App

加入删除和增添功能


import { useDynamicList } from "ahooks"; 
import { MinusCircleOutlined ,PlusCircleOutlined} from "@ant-design/icons";

function App() {
    const { list, remove,insert, replace } = useDynamicList(['David', 'Jack']);
  return (
    <div>
      {list.map((item, index) => {
        return (
          <div key={index}>
            <input type="text" value={item} onChange={ (e)=>replace(index,e.target.value)} />
            <MinusCircleOutlined onClick={()=>remove(index)}/>
            <PlusCircleOutlined onClick={() => insert(index+1,'')} />
        </div>
       )
      })}
      <br />
        <ul>
          {list.map((item, index) => (
            <li key={index}>
              {item}
            </li>
          ))}
       </ul>
      </div>
    )
}
export default App


http://www.kler.cn/a/568602.html

相关文章:

  • 2025国家护网HVV高频面试题总结来了01(题目+回答)
  • Django模型管理器/QuerySet 常见的方法
  • Python基于交互注意力的深度时空网络融合多源信息的剩余寿命预测方法
  • DeepSeek-R1私有化部署——使用Python实现DeepSeek-R1-Distill-Qwen模型部署调用与流式输出
  • 青海高校迎新系统的实施与影响
  • Qwen2-Audio系列学习笔记
  • TrustRAG:通过配置化模块化的检索增强生成(RAG)框架提高生成结果的可靠性和可追溯性
  • HIVE数据加载
  • LeetCode 202. 快乐数 java题解
  • uniapp 中引入使用uView UI
  • 前端文件分片上传深度解析:从原理到实践
  • 大模型微调入门(Transformers + Pytorch)
  • YOLOv8目标检测推理流程及C++代码
  • 5分钟看懂Deepseek开源周之六:Deepseek-V3/R1推理系统设计----揭开深度求索模型系统设计和运营成本之谜
  • 河南理工XCPC萌新选拔赛
  • 蓝桥杯备赛-前缀和-可获得的最小取值
  • fiscoBcos中手动部署webase-front
  • 《白帽子讲 Web 安全》之移动 Web 安全
  • 分布式微服务系统架构第92集:智能健康监测设备Java开发方案
  • 【Java项目】基于SpringBoot的地方废物回收机构管理系统