昨天晚上刚学完已经一点了,来不及写笔记,主要是想睡觉哈,所以今天补上,我发现效率还挺高的,今天重新做笔记,加固了昨天的知识点,要不以后都这样子哈,学完第二天再写哈,要是大家有推荐的vue项目练手可不可以分享给我,跪求
React表单控制
受控绑定
概念:使用React组件的状态(useState)控制表单的状态
受控表单:
第一步:声明一个react状态--useState
第二步:通过value属性绑定react状态
第三步:绑定onChange事件,通过事件参数e拿到输入框的最新值,反向修改到react状态中
import {useState} from 'react'
function App(){
const [value, setValue] = useState('')
return (
<input
type="text"
value={value}
onChange={e => setValue(e.target.value)}
/>
)
}
非受控绑定
概念:通过获取DOM的方式获取表单的输入数据
react 获取dom
第一步:useRef生成ref对象,绑定到dom标签上
第二步:dom可用时(渲染完毕之后dom生成之后才可用),ref.current获取dom
import {useRef} from 'react'
function App(){
const inputRef = useRef(null)
const onChange = ()=>{
console.log(inputRef.current.value)
}
return (
<input
type="text"
ref={inputRef}
onChange={onChange}
/>
)
}
React组件通信
概念:组件通信就是组件之间的数据传递
, 根据组件嵌套关系的不同,有不同的通信手段和方法
父子通信-父传子
实现步骤
-
父组件传递数据 - 在子组件标签上绑定属性
-
子组件接收数据 - 子组件通过props参数接收数据
-
props:对象里面包含了父组件的传递过来的所有数据
function Son(props){
return <div>{ props.v }</div>
}
function App(){
const name = 'this is app name'
return (
<div>
<Son v={name}/>
</div>
)
}
props说明
props可以传递任意的合法数据,比如数字、字符串、布尔值、数组、对象、函数、JSX
props是只读对象子组件只能读取props中的数据,不能直接进行修改, 父组件的数据只能由父组件修改
父传子 - 特殊的prop children
当我们把内容嵌套在组件的标签内部时,组件会自动在名为children的prop属性中接收该内容
父子通信-子传父
核心思路:在子组件中调用父组件中的函数并传递参数
首先给子组件标签传递一个父组件中的函数,传过去之后子组件接收,在子组件通过某些事件调用起来,同时把自己的数据当作实参,传给父组件,父组件中的函数写一个形参接收
function Son({ onGetMsg }){
const sonMsg = 'this is son msg'
return (
<div>
{/* 在子组件中执行父组件传递过来的函数 */}
<button onClick={()=>onGetMsg(sonMsg)}>send</button>
</div>
)
}
function App(){
//加一个状态数据
const {value,setSa}=useState('')
const getMsg = (msg)
=>{
console.log(msg)
setSa(msg)
}
return (
<div>
{/* 传递父组件中的函数到子组件 */}
<Son onGetMsg={ getMsg }/>
{msg}
</div>
)
}
兄弟组件通信
实现思路: 借助 状态提升
机制,通过共同的父组件进行兄弟之间的数据传递
-
A组件先通过子传父的方式把数据传递给父组件App
-
App拿到数据之后通过父传子的方式再传递给B组件
// A->App
import { useState } from "react"
function A({ i }) {
const n = 'this A'
return (
<div>
this is A compnent,
<button onClick={() => i(n)}>123</button>
</div>
)
}
function B() {
return (
<div>
this is B compnent,
</div>
)
}
function App() {
const [name, setAa] = useState
const getAname = (name) => {
setAa(name)
console.log(name);
}
return (
<div>
this is App
<A i={getAname}></A>
</div>
)
}
export default App
// A->App App->B
import { useState } from "react"
function A({ i }) {
const n = 'this A'
return (
<div>
this is A compnent,
<button onClick={() => i(n)}>123</button>
</div>
)
}
// 解构出来的x
function B({ x }) {
return (
<div>
this is B compnent,
{x}
</div>
)
}
function App() {
// 要想把a的数据传给B,则app要准备一个数据用来接受a传过来的数据,
//并且希望b可以动态的显示这个数据,则需要状态变量
const [name, setAa] = useState('')
const getAname = (name) => {
console.log(name);
setAa(name)
}
return (
<div>
this is App
<A i={getAname}></A>
<B x={name}></B>
</div>
)
}
export default App
跨层组件通信
实现步骤:
-
使用
createContext
方法创建一个上下文对象Ctx -
在顶层组件(App)中通过
Ctx.Provider
组件提供数据 -
在底层组件(B)中通过
useContext
钩子函数获取消费数据
//App->A->B
import { createContext, useContext } from "react"
// 1. createContext方法创建一个上下文对象
const Asdf = createContext()
function A() {
return (
<div>
this is A compnent,
<B></B>
</div>
)
}
function B() {
// 3. 在底层组件 通过useContext钩子函数使用数据
const qwe = useContext(Asdf)
return (
<div>
this is B compnent,{qwe}
</div>
)
}
function App() {
const qwe = 'this App'
return (
<div>
{/* 2. 在顶层组件 通过Provider组件提供数据 */}
<Asdf.Provider value={qwe}>
this is App
<A></A>
</Asdf.Provider>
</div>
)
}
export default App
React副作用管理-useEffect
概念理解
useEffect是一个React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作(副作用), 比如发送AJAX请求,更改DOM等等
说明:
-
参数1是一个函数,可以把它叫做副作用函数,在函数内部可以放置要执行的操作
-
参数2是一个数组(可选参),在数组里放置依赖项,不同依赖项会影响第一个参数函数的执行,当是一个空数组的时候,副作用函数只会在组件渲染完毕之后执行一次
import { useEffect, useState } from 'react'
const URL = 'http://geek.itheima.net/v1_0/channels'
function App() {
// 之后才创建一个状态
const [list, setSt] = useState([])
useEffect(() => {
async function getL() {
const res = await fetch(URL)
const i = await res.json()
console.log(i);
setSt(i.data.channels)
}
getL()
}, [])
return (
<div>
this is app
<ul>
{list.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
</div>
)
}
export default App
useEffect依赖说明
useEffect副作用函数的执行时机存在多种情况,根据传入依赖项的不同,会有不同的执行表现
依赖项 | 副作用功函数的执行时机 |
---|---|
没有依赖项 | 组件初始渲染 + 组件更新时执行 |
空数组依赖 | 只在初始渲染时执行一次 |
添加特定依赖项 | 组件初始渲染 + 依赖项变化时执行 |
import { useEffect, useState } from 'react'
function App() {
const [count, setCount] = useState(0)
//useEffect(() => {
// console.log('fu');
//})
// useEffect(() => {
// console.log('fu');
// }, [])
useEffect(() => {
console.log('fu');
}, [count])
return (
<div>
this is app
<button onClick={() => setCount(count + 1)}>++{count}</button>
</div>
)
}
export default App
清除副作用
概念:在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
自定义Hook实现
概念:自定义Hook是以 use打头的函数
,通过自定义Hook函数可以用来实现逻辑的封装和复用
import { useEffect, useState } from 'react'
function App() {
const [show, setShow] = useState(true)
const v = () => setShow(!show)
return (
<div>
{show && <div>显示与隐藏</div>}
<button onClick={v} >asd</button>
</div>
)
}
export default App
封装自定义hook通用思路
1. 声明一个以use打头的函数
2. 在函数体内封装可复用的逻辑(只要是可复用的逻辑)
3. 把组件中用到的状态或者回调return出去(以对象或者数组)
4. 在哪个组件中要用到这个逻辑,就执行这个函数,解构出来状态和回调进行使用
import { useEffect, useState } from 'react'
// 封装自定义Hook
// 问题: 布尔切换的逻辑 当前组件耦合在一起的 不方便复用
// 解决思路: 自定义hook
function useToggle() {
// 可复用的逻辑代码
const [show, setShow] = useState(true)
const v = () => setShow(!show)
// 哪些状态和回调函数需要在其他组件中使用 return
return { show, v }
}
function App() {
const { show, v } = useToggle()
return (
<div>
{show && <div>显示与隐藏</div>}
<button onClick={v} >asd</button>
</div>
)
}
export default App
React Hooks使用规则
-
只能在组件中或者其他自定义Hook函数中调用
-
只能在组件的顶层调用,不能嵌套在if、for、其它的函数中