# typora-images **Repository Path**: liuhuo-antares/typora-images ## Basic Information - **Project Name**: typora-images - **Description**: typora笔记专用图床 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-11-19 - **Last Updated**: 2023-06-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 1. JSX ![image-20230326170914985](https://imzbf.github.io/md-editor-rt/imgs/mark_emoji.gif) ## 1.1JSX的基本使用 ![image-20230326171129357](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326171129357.png) ![image-20230326171223098](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326171223098.png) ![image-20230326171256087](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326171256087.png) ![image-20230326171342549](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326171342549.png) ![image-20230326171539677](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326171539677.png) ![image-20230326171751510](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326171751510.png) ## 1.2 JSX中使用JS表达式 ![image-20230326171833123](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326171833123.png) ![image-20230326172112791](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326172112791.png) ## 1.3 JSX的条件渲染 ![image-20230326172332829](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326172332829.png) ## 1.4 JSX的列表渲染 ![image-20230326205010899](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326205010899.png) ## 1.5 JSX的样式处理 ![image-20230326205408331](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326205408331.png) ![image-20230326205620902](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326205620902.png) ----- # 2. React组件基础 ## 2.1 介绍 ![image-20230326205714669](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326205714669.png) ## 2.2 组件的两种创建方式 ### 2.2.1 方法创建 ![image-20230326210051510](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326210051510.png) ### 2.2.2 类创建 ![image-20230326210202303](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326210202303.png) ### 2.2.3 抽离为独立js文件 ![image-20230326210413553](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326210413553.png) ## 2.3 事件处理 ### 2.3.1事件绑定 ![image-20230326210650300](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326210650300.png) ### 2.3.2 事件对象 ![image-20230326210817151](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326210817151.png) ## 2.4 有状态组件和无状态组件 ![image-20230326210951358](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326210951358.png) ## 2.5 组件中的state和setState ### 2.5.1 state的基本使用 ![image-20230326211148358](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326211148358.png) this.state获取状态 ### 2.5.2 setState修改状态 ![image-20230326211542047](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326211542047.png) ## 2.6 抽离事件处理程序 ### 2.6.1 this指向问题 ![image-20230326211759165](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326211759165.png) 解决方案: ![image-20230326211835300](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326211835300.png) ![image-20230326212030010](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326212030010.png) ![image-20230326212125494](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326212125494.png) ![image-20230326212224617](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326212224617.png) ## 2.7 表单处理 ### 2.7.1 受控组件 ![image-20230326212430542](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326212430542.png) ![image-20230326212523240](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326212523240.png) ### 2.7.2 优化 ![image-20230326212943667](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326212943667.png) ### 2.7.3 非受控组件 ![image-20230326213240091](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326213240091.png) --- # 3. 组件高级 ## 3.1 组件通讯介绍 ![image-20230326214331431](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326214331431.png) ## 3.2 组件的props ### 3.2.1 基本使用 ![image-20230326214638711](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326214638711.png) ### 3.2.2 特点 ![image-20230326214923435](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326214923435.png) ![image-20230326214942494](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326214942494.png) ## 3.3 组件通讯方式 ### 3.3.1 父传子 ![image-20230326215144349](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326215144349.png) ### 3.3.2 子传父 ![image-20230326223125706](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326223125706.png) ![image-20230326223207861](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326223207861.png) ### 3.3.3兄弟组件通讯 ![image-20230326223820791](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326223820791.png) ![image-20230326224135035](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326224135035.png) ## 3.4 Context 类似于Vue中的消息总线 ![image-20230326224238446](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326224238446.png) ![image-20230326224322314](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326224322314.png) ![image-20230326224543153](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326224543153.png) ## 3.5 props深入 ### 3.5.1 children属性 ![image-20230326224924139](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326224924139.png) ### 3.5.2 props校验 ![image-20230326225123939](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225123939.png) ![image-20230326225206614](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225206614.png) ![image-20230326225239187](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225239187.png) ![image-20230326225535270](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225535270.png) ### 3.5.3 props默认值 ![image-20230326225640157](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225640157.png) # 4. 组件的生命周期 ## 4.1 概述 ![image-20230326225749940](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225749940.png) ## 4.2 三个阶段 ![image-20230326225825752](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225825752.png) ### 4.2.1 创建时 ![image-20230326225924502](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326225924502.png) render中调用setState会导致递归渲染 componentDidMound之后才能拿到DOM元素(getElementById) ### 4.2.2 更新时 ![image-20230326230453042](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326230453042.png) ![image-20230326230815625](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326230815625.png) 但是setState了还是会重新render和componentDidUpdate ### 4.2.3 卸载时 一般是清理定时器 ![image-20230326231202574](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326231202574.png) ## 4.3 其他钩子函数 ![image-20230326231312810](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326231312810.png) ## 4.4 render props和高阶组件 ### 4.4.1 概述 ![image-20230326231741302](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326231741302.png) ### 4.4.2 render props模式 ![image-20230326231950189](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326231950189.png) ![image-20230326232427586](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326232427586.png) #### 重点 ![image-20230326232905439](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326232905439.png) ![image-20230326233046778](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326233046778.png) ### 4.4.3 高阶组件 ![image-20230326233340330](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326233340330.png) ![image-20230326233528182](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326233528182.png) ![image-20230326233724048](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326233724048.png) ![image-20230326234220516](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326234220516.png) ![image-20230326234653504](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230326234653504.png) --- # 5. 原理篇 - setState()是异步更新数据的,如果在setState()之后立即打印数据,打印的是旧值==>后面的setState不能依赖于前面setState的结果 - setState()和render()不是一一对应的,多次setState()可能render一次 - this.setState((state, props) => {return {count: state.count+1}})这样也是异步更新的,但是可以保证更新顺序,这也是**setState的正确使用姿势**。 - this.setState((state, props) => {}, ()=>{//这个函数会在setState页面重新渲染之后执行}) - 父组件重新渲染时,其所有的子组件也会重新渲染 优化 - 减轻state,和渲染无关的属性,直接交给this,不要放进state(如计时器id) - 避免不必要渲染,通过shouldComponentUpdate(nextProps, nextState)钩子函数判断是否需要更新(返回true/false,nextProps和nextProps中存储的是将要更新的props和nextProps) - 纯组件PureComponent自动实现了shouldComponentUpdate钩子,不需要手动比较(白学!以后组件都extends React.PureComponent就行了) - 纯组件的实现原理是浅层对比:值类型比较直,引用类型值比较引用(这意味着数组修改其中的元素是不会重新渲染的!!!...不要用PureComponent,或者对数组进行修改时,不要使用push等方法,而是使用concat或slice或[...this.state.list, {新数据}],对对象的属性进行修改时,const newObj = {...state.obj, number: 2}; setState({obj: newObj}) - Diff算法:部分更新,只更新变化的地方 # 6. React路由 ## 6.1 基本使用 路由的原理是location.history的监听 ``` yarn add react-router-dom@6 ``` ![image-20230327002831603](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327002831603.png) ## 6.2 BrowerRouter和HashRouter ![image-20230327003005216](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327003005216.png) ## 6.3 Link&Routes&Route ![image-20230327003217692](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327003217692.png) ![image-20230327003109045](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327003109045.png) ![image-20230327003136513](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327003136513.png) ## 6.4 编程式导航 ![image-20230327003356120](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327003356120.png) ![image-20230327003519475](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327003519475.png) ## 6.5 路由传参 ### 6.5.1 searchParams ![image-20230327004031284](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327004031284.png) ### 6.5.2 params ![image-20230327004442400](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327004442400.png) ``` import useParams from 'react-router-dom' function About() { const params = useParams(); params.id拿到传过来的id } ``` ## 6.6 嵌套路由 ![image-20230327005037831](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327005037831.png) ![image-20230327005229499](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327005229499.png) ## 6.7 404路由 ![image-20230327005555101](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327005555101.png) # 7. Hooks # Hooks基础 ## Hooks概念理解 `本节任务:` 能够理解hooks的概念及解决的问题 ### 1. 什么是hooks Hooks的本质:**一套能够使函数组件更强大,更灵活的“钩子”** React体系里组件分为 类组件 和 函数组件 经过多年的实战,函数组件是一个更加匹配React的设计理念 `UI = f(data)`,也更有利于逻辑拆分与重用的组件表达形式,而先前的函数组件是不可以有自己的状态的,为了能让函数组件可以拥有自己的状态,所以从react v16.8开始,Hooks应运而生 **注意点:** 1. 有了hooks之后,为了兼容老版本,class类组件并没有被移除,俩者都可以使用 2. 有了hooks之后,不能在把函数成为无状态组件了,因为hooks为函数组件提供了状态 3. hooks只能在函数组件中使用 ### 2. Hooks解决了什么问题 Hooks的出现解决了俩个问题 1. 组件的状态逻辑复用 2.class组件自身的问题 1. 组件的逻辑复用 在hooks出现之前,react先后尝试了 mixins混入,HOC高阶组件,render-props等模式 但是都有各自的问题,比如mixin的数据来源不清晰,高阶组件的嵌套问题等等 2. class组件自身的问题 class组件就像一个厚重的‘战舰’ 一样,大而全,提供了很多东西,有不可忽视的学习成本,比如各种生命周期,this指向问题等等,而我们更多时候需要的是一个轻快灵活的'快艇' ## useState ### 1. 基础使用 `本节任务:` 能够学会useState的基础用法 **作用** useState为函数组件提供状态(state) **使用步骤** 1. 导入 `useState` 函数 2. 调用 `useState` 函数,并传入状态的初始值 3. 从`useState`函数的返回值中,拿到状态和修改状态的方法 4. 在JSX中展示状态 5. 调用修改状态的方法更新状态 **代码实现** ```jsx import { useState } from 'react' function App() { // 参数:状态初始值比如,传入 0 表示该状态的初始值为 0 // 返回值:数组,包含两个值:1 状态值(state) 2 修改该状态的函数(setState) const [count, setCount] = useState(0) return ( ) } export default App ``` ### 2. 状态的读取和修改 `本节任务:` 能够理解useState下状态的读取和修改 **读取状态** 该方式提供的状态,是函数内部的局部变量,可以在函数内的任意位置使用 **修改状态** 1. setCount是一个函数,参数表示`最新的状态值` 2. 调用该函数后,将使用新值替换旧值 3. 修改状态后,由于状态发生变化,会引起视图变化 **注意事项** 1. 修改状态的时候,一定要使用新的状态替换旧的状态,不能直接修改旧的状态,尤其是引用类型 ### 3. 组件的更新过程 `本节任务:` 能够理解使用hook之后组件的更新情况 函数组件使用 **useState** hook 后的执行过程,以及状态值的变化 - 组件第一次渲染 1. 1. 从头开始执行该组件中的代码逻辑 2. 调用 `useState(0)` 将传入的参数作为状态初始值,即:0 3. 渲染组件,此时,获取到的状态 count 值为: 0 - 组件第二次渲染 1. 1. 点击按钮,调用 `setCount(count + 1)` 修改状态,因为状态发生改变,所以,该组件会重新渲染 2. 组件重新渲染时,会再次执行该组件中的代码逻辑 3. 再次调用 `useState(0)`,此时 **React 内部会拿到最新的状态值而非初始值**,比如,该案例中最新的状态值为 1 4. 再次渲染组件,此时,获取到的状态 count 值为:1 注意:**useState 的初始值(参数)只会在组件第一次渲染时生效**。也就是说,以后的每次渲染,useState 获取到都是最新的状态值,React 组件会记住每次最新的状态值 ```jsx import { useState } from 'react' function App() { const [count, setCount] = useState(0) // 在这里可以进行打印测试 console.log(count) return ( ) } export default App ``` ### 4. 使用规则 `本节任务:` 能够记住useState的使用规则 1. `useState` 函数可以执行多次,每次执行互相独立,每调用一次为函数组件提供一个状态 ```javascript function List(){ // 以字符串为初始值 const [name, setName] = useState('cp') // 以数组为初始值 const [list,setList] = useState([]) } ``` 1. `useState` 注意事项 1. 1. 只能出现在函数组件或者其他hook函数中 2. 不能嵌套在if/for/其它函数中(react按照hooks的调用顺序识别每一个hook) ```javascript let num = 1 function List(){ num++ if(num / 2 === 0){ const [name, setName] = useState('cp') } const [list,setList] = useState([]) } // 俩个hook的顺序不是固定的,这是不可以的!!! ``` 1. 1. 可以通过开发者工具查看hooks状态 ## useEffect(有点类似watch) ### 1. 理解函数副作用 `本节任务:` 能够理解副作用的概念 **什么是副作用** 副作用是相对于主作用来说的,一个函数除了主作用,其他的作用就是副作用。对于 React 组件来说,**主作用就是根据数据(state/props)渲染 UI**,除此之外都是副作用(比如,手动修改 DOM) **常见的副作用** 1. 数据请求 ajax发送 2. 手动修改dom 3. localstorage操作 useEffect函数的作用就是为react函数组件提供副作用处理的! ### 2. 基础使用 `本节任务:` 能够学会useEffect的基础用法并且掌握默认的执行执行时机 **作用** 为react函数组件提供副作用处理 **使用步骤** 1. 导入 `useEffect` 函数 2. 调用 `useEffect` 函数,并传入回调函数 3. 在回调函数中编写副作用处理(dom操作) 4. 修改数据状态 5. 检测副作用是否生效 **代码实现** ```jsx import { useEffect, useState } from 'react' function App() { const [count, setCount] = useState(0) useEffect(()=>{ // dom操作 document.title = `当前已点击了${count}次` }) return ( ) } export default App ``` ### 3. 依赖项控制执行时机 `本节任务:` 能够学会使用依赖项控制副作用的执行时机 **1. 不添加依赖项** 组件首次渲染执行一次,以及不管是哪个状态更改引起组件更新时都会重新执行 1. 组件初始渲染 2. 组件更新 (不管是哪个状态引起的更新) ```jsx useEffect(()=>{ console.log('副作用执行了') }) ``` **2. 添加空数组** 组件只在首次渲染时执行一次 ```jsx useEffect(()=>{ console.log('副作用执行了') },[]) ``` **3. 添加特定依赖项** 副作用函数在首次渲染时执行,在依赖项发生变化时重新执行 ```jsx function App() { const [count, setCount] = useState(0) const [name, setName] = useState('zs') useEffect(() => { console.log('副作用执行了') }, [count]) return ( <> ) } ``` **注意事项** useEffect 回调函数中用到的数据(比如,count)就是依赖数据,就应该出现在依赖项数组中,如果不添加依赖项就会有bug出现 ### 4. 清理副作用 如果想要清理副作用 可以在副作用函数中的末尾return一个新的函数,在新的函数中编写清理副作用的逻辑 注意执行时机为: 1. 组件卸载时自动执行 2. 组件更新时,下一个useEffect副作用函数执行之前自动执行 ```jsx import { useEffect, useState } from "react" const App = () => { const [count, setCount] = useState(0) useEffect(() => { const timerId = setInterval(() => { setCount(count + 1) }, 1000) return () => { // 用来清理副作用的事情 clearInterval(timerId) } }, [count]) return (
{count}
) } export default App ``` ## 阶段小练习 - 自定义hook **需求描述**:自定义一个hook函数,实现获取滚动距离Y ``` const [y] = useWindowScroll() import { useState, useEffect } from "react" export function useWindowScroll () { const [y, setY] = useState(0) useEffect(()=>{ const scrollHandler = () => { const h = document.documentElement.scrollTop setY(h) }) window.addEventListener('scroll', scrollHandler) return () => window.removeEventListener('scroll', scrollHandler) }) return [y] } ``` **需求描述:** 自定义hook函数,可以自动同步到本地LocalStorage ``` const [message, setMessage] = useLocalStorage(key,defaultValue) ``` 1. message可以通过自定义传入默认初始值 2. 每次修改message数据的时候 都会自动往本地同步一份 ```javascript import { useEffect, useState } from 'react' export function useLocalStorage (key, defaultValue) { const [message, setMessage] = useState(defaultValue) // 每次只要message变化 就会自动同步到本地ls useEffect(() => { window.localStorage.setItem(key, message) }, [message, key]) return [message, setMessage] } ``` # Hooks进阶 ## useState - 回调函数的参数 `本节任务:` 能够理解useState回调函数作为参数的使用场景 **使用场景** 参数只会在组件的初始渲染中起作用,后续渲染时会被忽略。如果初始 state 需要通过计算才能获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用 **语法** ```jsx const [name, setName] = useState(()=>{ // 编写计算逻辑 return '计算之后的初始值' }) ``` **语法规则** 1. 回调函数return出去的值将作为 `name` 的初始值 2. 回调函数中的逻辑只会在组件初始化的时候执行一次 **语法选择** 1. 如果就是初始化一个普通的数据 直接使用 `useState(普通数据)` 即可 2. 如果要初始化的数据无法直接得到需要通过计算才能获取到,使用`useState(()=>{})` **来个需求** ```jsx import { useState } from 'react' function Counter(props) { const [count, setCount] = useState(() => { return props.count }) return (
) } function App() { return ( <> ) } export default App ``` ## useEffect - 发送网络请求 `本节任务:` 能够掌握使用useEffect hook发送网络请求 **使用场景** 如何在useEffect中发送网络请求,并且封装同步 async await操作 **语法要求** 不可以直接在useEffect的回调函数外层直接包裹 await ,因为**异步会导致清理函数无法立即返回** ```javascript useEffect(async ()=>{ const res = await axios.get('http://geek.itheima.net/v1_0/channels') console.log(res) },[]) ``` **正确写法** 在内部单独定义一个函数,然后把这个函数包装成同步 ```jsx useEffect(()=>{ async function fetchData(){ const res = await axios.get('http://geek.itheima.net/v1_0/channels') console.log(res) } },[]) ``` ## useRef `本节任务:` 能够掌握使用useRef获取真实dom或组件实例的方法 **使用场景** 在函数组件中获取真实的dom元素对象或者是组件对象 **使用步骤** 1. 导入 `useRef` 函数 2. 执行 `useRef` 函数并传入null,返回值为一个对象 内部有一个current属性存放拿到的dom对象(组件实例) 3. 通过ref 绑定 要获取的元素或者组件 **获取dom** ```jsx import { useEffect, useRef } from 'react' function App() { const h1Ref = useRef(null) useEffect(() => { console.log(h1Ref) },[]) return (

this is h1

) } export default App ``` **获取组件实例** 函数组件由于没有实例,不能使用ref获取,如果想获取组件实例,必须是类组件 ```jsx class Foo extends React.Component { sayHi = () => { console.log('say hi') } render(){ return
Foo
} } export default Foo ``` ```jsx import { useEffect, useRef } from 'react' import Foo from './Foo' function App() { const h1Foo = useRef(null) useEffect(() => { console.log(h1Foo) }, []) return (
) } export default App ``` ## useContext(跨组件传输数据,掌握了!) `本节任务:` 能够掌握hooks下的context使用方式 **实现步骤** 1. 使用`createContext` 创建Context对象 2. 在顶层组件通过`Provider` 提供数据 3. 在底层组件通过`useContext`函数获取数据 **代码实现** ```jsx import { createContext, useContext } from 'react' // 创建Context对象 const Context = createContext() function Foo() { return
Foo
} function Bar() { // 底层组件通过useContext函数获取数据 const name = useContext(Context) return
Bar {name}
} function App() { return ( // 顶层组件通过Provider 提供数据
) } export default App ``` ## 阶段小练习-todoMvc-hook版 案例仓库地址:https://gitee.com/react-course-series/react-tomvc-hook 1. 克隆项目到本地 ```bash $ git clone https://gitee.com/react-course-series/react-tomvc-hook.git ``` 1. 安装必要依赖 ```bash $ yarn ``` 1. 开启mock接口服务,**保持窗口不关闭** !!!!! ```bash # 启动mock服务 $ yarn mock-serve ``` 1. **另起一个bash窗口**开启前端服务 ```bash $ yarn start ``` 1. 浏览器输入 localhost:3000演示效果 **项目开发步骤:** 1. 切换到todo-test分支 ```bash $ git checkout todo-test ``` 1. 打开 app.js 已有基础样板代码,在这个基础上编写业务逻辑即可 2. 接口文档 | 接口作用 | 接口地址 | 接口方法 | 接口参数 | | -------- | ------------------------------------------------------------ | -------- | ---------------------- | | 获取列表 | http://localhost:3001/data | GET | 无 | | 删除 | http://localhost:3001/data/:id | DELETE | id | | 搜索 | [http://localhost:3001/data/?name=keyword](http://localhost:3001/data/?q=keyword) | GET | name(以name字段搜索) | **实现功能** | 功能 | 核心思路 | | ------------ | ------------------------------------ | | 表格数据渲染 | elementPlus el-table组件使用 | | 删除功能 | 获取当前id 调用接口 | | 搜索功能 | 用的依旧是列表接口,多传一个name参数 | | 清除搜索功能 | 清空搜索参数 重新获取列表 | # mbox ![image-20230327200832951](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327200832951.png) ## 响应式 ![image-20230327201853326](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327201853326.png) ## 计算属性 ![image-20230327202340360](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327202340360.png) ## 模块化 ![image-20230327202457851](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327202457851.png) ![image-20230327202935042](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327202935042.png) ![image-20230327202943568](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327202943568.png) ![image-20230327203659516](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327203659516.png) ## 总结 ![image-20230327203801302](https://gitee.com/liuhuo-antares/typora-images/raw/master/image/image-20230327203801302.png)