React18学习

基本来说和之前的没有什么太大区别,之前一直用的vue,纯粹当复习一遍react了

快捷键

rsc --> 自动创建函数式组件
rsi --> 自动创建函数式组件且带props
rcc --> 自动创建类组件
类组件的props是自动存储到类的实例对象中了,可直接通过实例对象访问,也就是this.props.xxx

一 组件传参

1) 父传子

1 props (类组件使用this.props)

-单向传递,子组件只能接收无法反向修改

// 父组件
import ReactDom from 'react-dom/client'
import Progeny from './progeny' // 引入子组件

const App = () => { // 父组件jsx代码
// 注意传递函数需要传一个完整的函数,例如fun={ alert('参数') }会在子组件直接执行
    return <div>
        <Progeny test='传家宝' num={ 123 } fun={ () => alert('传递了一个函数') }/>
    </div>
}

const root = ReactDom.createRoot(documnet.getElementById('root')) // 创建虚拟Dom
root.render(App) // 挂载写好的jsx结构
// 子组件
const Progeny = (props) => {
    console.log(props) // 会打印一个包含test,num,fun的对象
    props.fun && props.fun() // 执行父组件传递的函数
    return <div>
        { props.test }有{ props.num }个
    </div>
}

更新中。。。(肯定还有别的,暂时还没学到)

二 useState钩子

等同vue3中的ref,reactive作用一致

  1. 函数式组件

语法

1) 直接赋值
import { useState } from 'react'

const App = () => {
    const [count, setCount] = useState(1)
    const fun = () => { setCount(count + 1) }
    return <div>
        <button onClick={() => setCount(count - 1) }>-1</button>{ count }<button onClick={ fun }>+1</button>
    </div>
}

修改state的值必须使用setter设置器,使用setter设置器修改变量时,会触发render重新渲染组件,⚠️ 注意修改之后必须有变化才会重新渲染,diff算法会前后进行对比,如果没变化就什么也不会做

⚠️ 另外setter是修改变量的值,但如果是定义的引用类型数据,需要改变堆内存的值,的确是不需要使用setter,但是页面不会重新渲染所以看起来好像没有生效,所以改变引用类型数据的时候通常改变完需要使用setter重新赋值一次(跟vue一样,并且需要浅拷贝一下)

⚠️ 最后,setter修改一个state时,并不是代表把当前的state改掉了,而是改变下一次渲染的state值,并且setter是异步的,所以使用setter之后打印state的值还是没改变之前的值

2) 另外还可以在括号里传一个回调函数
import { useState } from 'react'

const App = () => {
    const counts = useState(1)
    const count = counts[0]
    const setCount = counts[1]
    // 此种写法与上面[xx, setxx]作用完全一致,只是提醒一下useState的返回值是一个数组,上述写法其实是把数组给解构了
    const fun = () => {
        setTimeout(() => {
            setCount(prev => prev + 1)
        }, 1000)
    }
    return <div>
        {
    
    { count }}
        <button onClick={ fun }>按钮</button>
    </div>
}

直接传回调与直接传值作用完全一样,只是两种写法的区别而已

⚠️ 但是setter是一种类似节流的机制,如果在很短时间之内多次触发,执行一次之后,在组件重新渲染之前,其他次都没有意义,因为state并没有实时改变,state + 1用的state一直是不变的,在大型项目里是可能出现问题的,当然使用回调也无法避免,所以react提供了回调函数的第一个参数是上一次state的值,使用该参数才会避免这种问题

  1. 类组件

类组件state同样也是放到state中了,但是仍旧与函数式组件有很大差异

语法

import React { Component } from 'react'

class App extends Component {
    state = { // 类组件定义state语法,所有要使用的状态都放到这个对象里
        count: 0
    }
    countHandler1 = () => { // 定义函数不需要const,其实就是定义一个类的方法
        this.setState({ count: this.state.count + 1 })
    // 类组件修改state时不需要浅靠谱原state,直接修改即可不会像,函数式组件那样覆盖没有修改的值
    // 但是如果修改的是state里定义的一个对象仍旧需要浅拷贝,这其实跟小程序的语法很相似
    }
    countHandler2 = () = > { // 同样的可以使用回调
        this.setState(prev => {
            return { count: prev.count + 1 } // 有一点要注意prev是指的整个state
        })
    }
    render() {
        return <div>
            { this.state.count } // 访问时都是需要this的
            <button onClick={ countHandler1 }>按钮</button>
            <button onClick={ countHandler2 }></button>
        </div>
    }
}

三 获取Dom

  1. 函数式组件

1)直接使用原生的document对象获取

这里就不写了,总之react里可以直接使用documnet直接获取dom,但是不推荐,或多或少的会多耗费一点性能(获取dom这事本身就耗性能,react提供的方式也好点有限,尽可能避免操作dom)

2) 通过ref
const { useRef } from 'react'

const App = () => {
    const divRef = useRef()
    console.log(divRef)  // 打印结果: { current: undefined }
    const fun = () => {
        console.log(divRef) // 打印结果: { current: div.div } 也就是dom元素
    }
    return <div>
        <div ref={ divRef }></div>
        <button onClick={ fun }>按钮</button> 
    </div>
}

同样的代码运行的时候还没有获取到,第一次渲染完才会吧dom赋值给选定的对象,current属性就是所需要操作的dom对象

⚠️ 这里ref只是提供一个存储用的对象,没有其他特殊的用途,自己创建一个{current: null}和useRef完全一致,两者的区别是自己创建的js对象每次渲染组件都会创建一次,会造成一些问题,而useRef创建的对象并不会随组件的创建而重新创建

❗所以useRef还有一个用途就是,如果需要一个随着组件更新不会改变的对象,就可以使用useRef

  1. 类组件

与函数式组件一致但是用的不是use了而是React.createRef(),原理类似,所以同样的,也可以自己创建一个空对象,不在赘述

import React , { Component } from 'react'

class App  extends Component {
    divRef = React.createRef()
    divHandler = () => {
        console.log(divRef)
    }
    render(){
        return <div>
            <div ref={ this.divRef }>这是一个类组件</div>
            <button onClick={ divHandler }>查看dom元素</button>
        </div>
    }
}

更新中。。。。(白天还要上班,有时间才能更新)

猜你喜欢

转载自blog.csdn.net/a9874561328/article/details/128742291