关于react

1.快速搭建开发环境

在这里插入图片描述

2.react渲染流程

在这里插入图片描述

在这里插入图片描述

3.1 jsx基础 概念

在这里插入图片描述

3.2 jsx基础 本质

在这里插入图片描述

3.3 jsx基础 jsx表达式

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e75894d47c014d8aaf44a49fda51cec6.png
!](https://img-blog.csdnimg.cn/direct/fa74d6a1dd3b45feaf5d2509cef01006.png)

3.4 jsx基础 实现列表渲染

在这里插入图片描述
在这里插入图片描述

3.5 jsx基础 实现条件渲染

在这里插入图片描述

3.5 jsx基础 实现复杂的条件渲染

在这里插入图片描述

4. react中事件绑定

在这里插入图片描述
在这里插入图片描述

5.react组建基础使用

在这里插入图片描述

6.1 useState

在这里插入图片描述
在这里插入图片描述

6.2 useState修改状态的规则

在这里插入图片描述
在这里插入图片描述

7.基础样式控制

在这里插入图片描述

8.1评论案例–删除列表

在这里插入图片描述
在这里插入图片描述

8.2评论案例–tab切换

在这里插入图片描述
在这里插入图片描述

8.2评论案例–排序

$ npm i --save lodash //安装lodash
import _ from 'loadsh';//引入loadsh

在这里插入图片描述

9.classnames优化类名控制

npm install classnames //安装classnames
import classNames from 'classnames';//引入classnames

在这里插入图片描述

10.受控表单绑定

在这里插入图片描述

11.react中获取DOM

在这里插入图片描述
在这里插入图片描述

11.1 react中组件通信—父传子

//1. 父组件传递数据 - 在子组件标签上绑定属性 
//2. 子组件接收数据 - 子组件通过props参数接收数据
//JSX
//子组件
function Son(props){
    
    
  return <div>{
    
     props.name }</div>
}
//父组件
function App(){
    
    
  const name = 'this is app name'
  return (
    <div>
       <Son name={
    
    name}/>
    </div>
  )
}

在这里插入图片描述
在这里插入图片描述

11.2 react中组件通信—子传父

//核心思路:在子组件中调用父组件中的函数并传递参数
function Son({
     
      onGetMsg }){
    
    
  const sonMsg = 'this is son msg'
  return (
    <div>
      {
    
    /* 在子组件中执行父组件传递过来的函数 */}
      <button onClick={
    
    ()=>onGetMsg(sonMsg)}>send</button>
    </div>
  )
}


function App(){
    
    
  const[msg,setMesg]=useState('')
  const getMsg = (msg)=>{
    
    
    console.log(msg)
    setMesg(msg)
  }
  return (
    <div>
    {
    
    msg}
      {
    
    /* 传递父组件中的函数到子组件 */}
       <Son onGetMsg={
    
     getMsg }/>
    </div>
  )
}

11.3 react中组件通信—兄弟传值

// 实现思路: 借助 `状态提升` 机制,通过共同的父组件进行兄弟之间的数据传递
// 1. A组件先通过子传父的方式把数据传递给父组件App
// 2. App拿到数据之后通过父传子的方式再传递给B组件

// 1. 通过子传父 A -> App
// 2. 通过父传子 App -> B
import {
    
     useState } from "react"

function A ({
     
      onGetAName }) {
    
    
  // Son组件中的数据
  const name = 'this is A name'
  return (
    <div>
      this is A compnent,
      <button onClick={
    
    () => onGetAName(name)}>send</button>
    </div>
  )
}

function B ({
     
      name }) {
    
    
  return (
    <div>
      this is B compnent,
      {
    
    name}
    </div>
  )
}

function App () {
    
    
  const [name, setName] = useState('')
  const getAName = (name) => {
    
    
    setName(name)
  }
  return (
    <div>
      this is App
      <A onGetAName={
    
    getAName} />
      <B name={
    
    name} />
    </div>
  )
}

export default App

11.4 react中组件通信—跨层级组件传值

//1. 使用 `createContext`方法创建一个上下文对象Ctx 
//2. 在顶层组件(App)中通过 `Ctx.Provider` 组件提供数据 
//3. 在底层组件(B)中通过 `useContext` 钩子函数获取消费数据
//jsx
// App -> A -> B

import {
    
     createContext, useContext } from "react"
// 1. createContext方法创建一个上下文对象
const MsgContext = createContext()
function A () {
    
    
  return (
    <div>
      this is A component
      <B />
    </div>
  )
}
function B () {
    
    
  // 3. 在底层组件 通过useContext钩子函数使用数据
  const msg = useContext(MsgContext)
  return (
    <div>
      this is B compnent,{
    
    msg}
    </div>
  )
}
function App () {
    
    
  const msg = 'this is app msg'
  return (
    <div>
      {
    
    /* 2. 在顶层组件 通过Provider组件提供数据 */}
      <MsgContext.Provider value={
    
    msg}>
        this is App
        <A />
      </MsgContext.Provider>
    </div>
  )
}

export default App

12.1 react—useEffect基础使用

//useEffect是一个React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作(副作用), 比 如发送AJAX请求,更改DOM等等 
//组件渲染完毕之后就需要和服务器要数据,整个过程属于“只由渲染引起的操作”
//1. 参数1是一个函数,可以把它叫做副作用函数,在函数内部可以放置要执行的操作 
//2. 参数2是一个数组(可选参),在数组里放置依赖项,不同依赖项会影响第一个参数函数的执行,当是一个空数组的时候,副作用函数只会在组件渲染完毕之后执行一次 
//需求:在组件渲染完毕之后,立刻从服务端获取平道列表数据并显示到页面中
import {
    
     useEffect, useState } from "react"
const URL = 'http://geek.itheima.net/v1_0/channels'
function App () {
    
    
  // 创建一个状态数据
  const [list, setList] = useState([])
  useEffect(() => {
    
    
    // 额外的操作 获取频道列表
    async function getList () {
    
    
      const res = await fetch(URL)
      const jsonRes = await res.json()
      console.log(jsonRes)
      setList(jsonRes.data.channels)
    }
    getList()
  }, [])
  return (
    <div>
      this is app
      <ul>
        {
    
    list.map(item => <li key={
    
    item.id}>{
    
    item.name}</li>)}
      </ul>
    </div>
  )
}

export default App

12.2 react—useEffect依赖参数项

import {
    
     useEffect, useState } from "react"

function App () {
    
    
  // 1. 没有依赖项  初始 + 组件更新
  const [count, setCount] = useState(0)
  // useEffect(() => {
    
    
  //   console.log('副作用函数执行了')
  // })

  // 2. 传入空数组依赖  初始执行一次
  // useEffect(() => {
    
    
  //   console.log('副作用函数执行了')
  // }, [])

  // 3. 传入特定依赖项  初始 + 依赖项变化时执行
  useEffect(() => {
    
    
    console.log('副作用函数执行了')
  }, [count])

  return (
    <div>
      this is app
      <button onClick={
    
    () => setCount(count + 1)}>+{
    
    count}</button>
    </div>
  )
}

export default App

12.3 react—useEffect清除副作用

//概念:在useEffect中编写的由渲染本身引起的对接组件外部的操作,社区也经常把它叫做副作用操作,比如在useEffect中开启了一个定时器,我们想在组件卸载时把这个定时器再清理掉,这个过程就是清理副作用
import {
    
     useEffect, useState } from "react"
function Son () {
    
    
  // 1. 渲染时开启一个定时器
  useEffect(() => {
    
    
    const timer = setInterval(() => {
    
    
      console.log('定时器执行中...')
    }, 1000)

    return () => {
    
    
      // 清除副作用(组件卸载时)
      clearInterval(timer)
    }
  }, [])
  return <div>this is son</div>
}
function App () {
    
    
  // 通过条件渲染模拟组件卸载
  const [show, setShow] = useState(true)
  return (
    <div>
      {
    
    show && <Son />}
      <button onClick={
    
    () => setShow(false)}>卸载Son组件</button>
    </div>
  )
}

export default App

13.1 react自定义hook

// 封装自定义Hook

// 问题: 布尔切换的逻辑 当前组件耦合在一起的 不方便复用

// 解决思路: 自定义hook

import {
    
     useState } from "react"

function useToggle () {
    
    
  // 可复用的逻辑代码
  const [value, setValue] = useState(true)

  const toggle = () => setValue(!value)

  // 哪些状态和回调函数需要在其他组件中使用 return
  return {
    
    
    value,
    toggle
  }
}

// 封装自定义hook通用思路

// 1. 声明一个以use打头的函数
// 2. 在函数体内封装可复用的逻辑(只要是可复用的逻辑)
// 3. 把组件中用到的状态或者回调return出去(以对象或者数组)
// 4. 在哪个组件中要用到这个逻辑,就执行这个函数,解构出来状态和回调进行使用


function App () {
    
    
  const {
    
     value, toggle } = useToggle()
  return (
    <div>
      {
    
    value && <div>this is div</div>}
      <button onClick={
    
    toggle}>toggle</button>
    </div>
  )
}

export default App

13.2 reactHooks的使用规则

在这里插入图片描述

13.3 封装请求数据的Hook

function useGetList () {
    
    
  // 获取接口数据渲染
  const [commentList, setCommentList] = useState([])
  useEffect(() => {
    
    
    // 请求数据
    async function getList () {
    
    
      // axios请求数据
      const res = await axios.get(' http://localhost:3004/list')
      setCommentList(res.data)
    }
    getList()
  }, [])

  return {
    
    
    commentList,
    setCommentList
  }
}

const app =()=>{
    
    
//使用
 const {
    
     commentList, setCommentList } = useGetList()
}

13.3 封装Item组件的Hook

// 封装Item组件
function Item ({
     
      item, onDel }) {
    
    
  return (
    <div className="reply-item">
      {
    
    /* 头像 */}
      <div className="root-reply-avatar">
        <div className="bili-avatar">
          <img
            className="bili-avatar-img"
            alt=""
            src={
    
    item.user.avatar}
          />
        </div>
      </div>

      <div className="content-wrap">
        {
    
    /* 用户名 */}
        <div className="user-info">
          <div className="user-name">{
    
    item.user.uname}</div>
        </div>
        {
    
    /* 评论内容 */}
        <div className="root-reply">
          <span className="reply-content">{
    
    item.content}</span>
          <div className="reply-info">
            {
    
    /* 评论时间 */}
            <span className="reply-time">{
    
    item.ctime}</span>
            {
    
    /* 评论数量 */}
            <span className="reply-time">点赞数:{
    
    item.like}</span>
            {
    
    /* 条件:user.id === item.user.id */}
            {
    
    user.uid === item.user.uid &&
              <span className="delete-btn" onClick={
    
    () => onDel(item.rpid)}>
                删除
              </span>}
          </div>
        </div>
      </div>
    </div>
  )
}

const App = () => {
    
    
  // 渲染评论列表
  // 1. 使用useState维护list
  // const [commentList, setCommentList] = useState(_.orderBy(list, 'like', 'desc'))
  const {
    
     commentList, setCommentList } = useGetList()

  // 删除功能
  const handleDel = (id) => {
    
    
    console.log(id)
    // 对commentList做过滤处理
    setCommentList(commentList.filter(item => item.rpid !== id))
  }
  return (
    <div className="app">
        {
    
    /* 评论列表 */}
        <div className="reply-list">
          {
    
    /* 评论项 */}
          {
    
    commentList.map(item => <Item key={
    
    item.id} item={
    
    item} onDel={
    
    handleDel} />)}
        </div>
      </div>
  )
}

export default App

14. redux

在这里插入图片描述
在这里插入图片描述

<button id="decrement">-</button>
<span id="count">0</span>
<button id="increment">+</button>

<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>

<script>
  // 1. 定义reducer函数 
  // 作用: 根据不同的action对象,返回不同的新的state
  // state: 管理的数据初始状态
  // action: 对象 type 标记当前想要做什么样的修改
  function reducer (state = {
     
      count: 0 }, action) {
    
    
    // 数据不可变:基于原始状态生成一个新的状态
    if (action.type === 'INCREMENT') {
    
    
      return {
    
     count: state.count + 1 }
    }
    if (action.type === 'DECREMENT') {
    
    
      return {
    
     count: state.count - 1 }
    }
    return state
  }

  // 2. 使用reducer函数生成store实例
  const store = Redux.createStore(reducer)

  // 3. 通过store实例的subscribe订阅数据变化
  // 回调函数可以在每次state发生变化的时候自动执行
  store.subscribe(() => {
    
    
    console.log('state变化了', store.getState())
    document.getElementById('count').innerText = store.getState().count
  })

  // 4. 通过store实例的dispatch函数提交action更改状态 
  const inBtn = document.getElementById('increment')
  inBtn.addEventListener('click', () => {
    
    
    // 增
    store.dispatch({
    
    
      type: 'INCREMENT'
    })
  })

  const dBtn = document.getElementById('decrement')
  dBtn.addEventListener('click', () => {
    
    
    // 减
    store.dispatch({
    
    
      type: 'DECREMENT'
    })
  })

  // 5. 通过store实例的getState方法获取最新状态更新到视图中

</script>

15.1 redux与react环境搭建

在这里插入图片描述

  1. 使用 CRA 快速创建 React 项目
npx create-react-app react-redux 
  1. 安装配套工具
npm i @reduxjs/toolkit  react-redux 
  1. 启动项目
npm run start 

在这里插入图片描述

15.2 redux与react实现counter

在这里插入图片描述

//store文件下的counterStrore.js
import {
    
     createSlice } from '@reduxjs/toolkit'
const counterStore = createSlice({
    
    
  // 模块名称独一无二
  name: 'counter',
  // 初始数据
  initialState: {
    
    
    count: 1
  },
  // 修改数据的同步方法
  reducers: {
    
    
    increment (state) {
    
    
      state.count++
    },
    decrement(state){
    
    
      state.count--
    }
  }
})
// 结构出actionCreater
const {
    
     increment,decrement } = counter.actions

// 获取reducer函数
const counterReducer = counterStore.reducer

// 导出
export {
    
     increment, decrement }
export default counterReducer
//stroe文件下的index.js
import {
    
     configureStore } from '@reduxjs/toolkit'
import counterReducer from './modules/counterStore'
const store = configureStore({
    
    
  reducer: {
    
    
    // 注册子模块
    counter: counterReducer
  }
})
export default store

在这里插入图片描述

```jsx
//index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
// 导入store
import store from './store'
// 导入store提供组件Provider
import {
    
     Provider } from 'react-redux'
ReactDOM.createRoot(document.getElementById('root')).render(
  // 提供store数据
  <Provider store={
    
    store}>
    <App />
  </Provider>
)

在这里插入图片描述
在这里插入图片描述

import {
    
     useDispatch, useSelector } from 'react-redux'
// 导入actionCreater
import {
    
     inscrement, decrement} from './store/modules/counterStore'
function App () {
    
    
  const {
    
     count } = useSelector(state => state.counter)
  const dispatch = useDispatch()
  return (
    <div className="App">
      <button onClick={
    
    () => dispatch(decrement())}>-</button>
      {
    
    count}
      <button onClick={
    
    () => dispatch(inscrement())}>+</button>
    </div>
  )
}

export default App

总结
在这里插入图片描述

15.3 redux与react 提交action参数

在这里插入图片描述

15.4 redux与react 异步状态操作

在这里插入图片描述

//channelStore.js文件
import {
    
     createSlice } from "@reduxjs/toolkit"
import axios from "axios"

const channelStore = createSlice({
    
    
  name: 'channel',
  initialState: {
    
    
    channelList: []
  },
  reducers: {
    
    
    setChannels (state, action) {
    
    
      state.channelList = action.payload
    }
  }
})


// 异步请求部分
const {
    
     setChannels } = channelStore.actions

const fetchChannlList = () => {
    
    
  return async (dispatch) => {
    
    
    const res = await axios.get('http://geek.itheima.net/v1_0/channels')
    dispatch(setChannels(res.data.data.channels))
  }
}
export {
    
     fetchChannlList }


```javascript
//在store文件下的index.js文件
import {
    
     configureStore } from "@reduxjs/toolkit"
// 导入子模块reducer
import counterReducer from './modules/counterStore'
import channelReducer from './modules/channelStore'
const store = configureStore({
    
    
  reducer: {
    
    
    counter: counterReducer,
    channel: channelReducer
  }
})
export default store
const reducer = channelStore.reducer
export default reducer
//app.js
import {
    
     useEffect } from 'react'
import {
    
     useDispatch, useSelector } from 'react-redux'
// 导入actionCreater
import {
    
     inscrement, decrement, addToNum } from './store/modules/counterStore'
import {
    
     fetchChannlList } from './store/modules/channelStore'
function App () {
    
    
  const {
    
     count } = useSelector(state => state.counter)
  const {
    
     channelList } = useSelector(state => state.channel)
  const dispatch = useDispatch()
  // 使用useEffect触发异步请求执行
  useEffect(() => {
    
    
    dispatch(fetchChannlList())
  }, [dispatch])
  return (
    <div className="App">
      <button onClick={
    
    () => dispatch(decrement())}>-</button>
      {
    
    count}
      <button onClick={
    
    () => dispatch(inscrement())}>+</button>
      <button onClick={
    
    () => dispatch(addToNum(10))}>add To 10</button>
      <button onClick={
    
    () => dispatch(addToNum(20))}>add To 20</button>
      <ul>
        {
    
    channelList.map(item => <li key={
    
    item.id}>{
    
    item.name}</li>)}
      </ul>
    </div>
  )
}
export default App

15.3 redux调试工具 devtools

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42268006/article/details/135124661