「React进阶」 React全部api解读+基础实践大全(夯实基础2万字总结) (React DOM)

简介: 一份不错的 React 学习指南

接下来,我们来一起研究react-dom中比较重要的api

react-dom.jpg

render

render 是我们最常用的react-domapi,用于渲染一个react元素,一般react项目我们都用它,渲染根部容器app

ReactDOM.render(element, container[, callback])

使用

ReactDOM.render(
    < App / >,
    document.getElementById('app')
)

ReactDOM.render会控制container容器节点里的内容,但是不会修改容器节点本身。

hydrate

服务端渲染用hydrate。用法与 render() 相同,但它用于在 ReactDOMServer 渲染的容器中对 HTML 的内容进行 hydrate 操作。

ReactDOM.hydrate(element, container[, callback])

createPortal

Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。createPortal 可以把当前组件或 element 元素的子节点,渲染到组件之外的其他地方。

那么具体应用到什么场景呢?

比如一些全局的弹窗组件model,<Model/>组件一般都写在我们的组件内部,倒是真正挂载的dom,都是在外层容器,比如body上。此时就很适合createPortalAPI。

createPortal接受两个参数:

ReactDOM.createPortal(child, container)

第一个: child 是任何可渲染的 React 子元素
第二个: container是一个 DOM 元素。

接下来我们实践一下:

function WrapComponent({
   
    children }){
   
   
    const domRef = useRef(null)
    const [ PortalComponent, setPortalComponent ] = useState(null)
    React.useEffect(()=>{
   
   
        setPortalComponent( ReactDOM.createPortal(children,domRef.current) )
    },[])
    return <div> 
        <div className="container" ref={
   
    domRef } ></div>
        {
   
    PortalComponent }
     </div>
}

class Index extends React.Component{
   
   
    render(){
   
   
        return <div style={
   
   {
   
    marginTop:'50px' }} >
             <WrapComponent>
               <div  >hello,world</div>
            </WrapComponent>
        </div>
    }
}

效果

createPortal.jpg

我们可以看到,我们children实际在container 之外挂载的,但是已经被createPortal渲染到container中。

unstable_batchedUpdates

react-legacy模式下,对于事件,react事件有批量更新来处理功能,但是这一些非常规的事件中,批量更新功能会被打破。所以我们可以用react-dom中提供的unstable_batchedUpdates 来进行批量更新。

一次点击实现的批量更新

class Index extends React.Component{
   
   
    constructor(props){
   
   
       super(props)
       this.state={
   
   
           numer:1,
       }
    }
    handerClick=()=>{
   
   
        this.setState({
   
    numer : this.state.numer + 1 })
        console.log(this.state.numer)
        this.setState({
   
    numer : this.state.numer + 1 })
        console.log(this.state.numer)
        this.setState({
   
    numer : this.state.numer + 1 })
        console.log(this.state.numer)
    }
    render(){
   
   
        return <div  style={
   
   {
   
    marginTop:'50px' }} > 
            <button onClick={
   
    this.handerClick } >click me</button>
        </div>
    }
}

效果

batch1.jpg

渲染次数一次。

批量更新条件被打破

 handerClick=()=>{
   
   
    Promise.resolve().then(()=>{
   
   
        this.setState({
   
    numer : this.state.numer + 1 })
        console.log(this.state.numer)
        this.setState({
   
    numer : this.state.numer + 1 })
        console.log(this.state.numer)
        this.setState({
   
    numer : this.state.numer + 1 })
        console.log(this.state.numer)
    })
  }

效果

batch2.jpg

渲染次数三次。

unstable_batchedUpdate助力

 handerClick=()=>{
   
   
        Promise.resolve().then(()=>{
   
   
            ReactDOM.unstable_batchedUpdates(()=>{
   
   
                this.setState({
   
    numer : this.state.numer + 1 })
                console.log(this.state.numer)
                this.setState({
   
    numer : this.state.numer + 1 })
                console.log(this.state.numer)
                this.setState({
   
    numer : this.state.numer + 1 })
                console.log(this.state.numer)
            }) 
        })
    }

渲染次数一次,完美解决批量更新问题。

flushSync

flushSync 可以将回调函数中的更新任务,放在一个较高的优先级中。我们知道react设定了很多不同优先级的更新任务。如果一次更新任务在flushSync回调函数内部,那么将获得一个较高优先级的更新。比如

ReactDOM.flushSync(()=>{
   
   
    /* 此次更新将设置一个较高优先级的更新 */
    this.setState({
   
    name: 'alien'  })
})

为了让大家理解flushSync,我这里做一个demo奉上,

/* flushSync */
import ReactDOM from 'react-dom'
class Index extends React.Component{
   
   
    state={
   
    number:0 }
    handerClick=()=>{
   
   
        setTimeout(()=>{
   
   
            this.setState({
   
    number: 1  })
        })
        this.setState({
   
    number: 2  })
        ReactDOM.flushSync(()=>{
   
   
            this.setState({
   
    number: 3  })
        })
        this.setState({
   
    number: 4  })
    }
    render(){
   
   
        const {
   
    number } = this.state
        console.log(number) // 打印什么??
        return <div>
            <div>{
   
    number }</div>
            <button onClick={
   
   this.handerClick} >测试flushSync</button>
        </div>
    }
}

先不看答案,点击一下按钮,打印什么呢?

我们来点击一下看看

flushSync.gif

打印 0 3 4 1 ,相信不难理解为什么这么打印了。

  • 首先 flushSync this.setState({ number: 3 })设定了一个高优先级的更新,所以3 先被打印
  • 2 4 被批量更新为 4

相信这个demo让我们更深入了解了flushSync

findDOMNode

findDOMNode用于访问组件DOM元素节点,react推荐使用ref模式,不期望使用findDOMNode

ReactDOM.findDOMNode(component)

注意的是:

  • 1 findDOMNode只能用在已经挂载的组件上。

  • 2 如果组件渲染内容为 null 或者是 false,那么 findDOMNode返回值也是 null

  • 3 findDOMNode 不能用于函数组件。

接下来让我们看一下,findDOMNode具体怎么使用的:

class Index extends React.Component{
   
   
    handerFindDom=()=>{
   
   
        console.log(ReactDOM.findDOMNode(this))
    }
    render(){
   
   
        return <div style={
   
   {
   
    marginTop:'100px' }} >
            <div>hello,world</div>
            <button onClick={
   
    this.handerFindDom } >获取容器dom</button>
        </div>
    }
}

效果:

findNodedom.gif

我们完全可以将外层容器用ref来标记,获取捕获原生的dom节点。

unmountComponentAtNode

DOM 中卸载组件,会将其事件处理器和 state 一并清除。 如果指定容器上没有对应已挂载的组件,这个函数什么也不会做。如果组件被移除将会返回 true ,如果没有组件可被移除将会返回 false

我们来简单举例看看unmountComponentAtNode如何使用?

function Text(){
   
   
    return <div>hello,world</div>
}

class Index extends React.Component{
   
   
    node = null
    constructor(props){
   
   
       super(props)
       this.state={
   
   
           numer:1,
       }
    }
    componentDidMount(){
   
   
        /*  组件初始化的时候,创建一个 container 容器 */
        ReactDOM.render(<Text/> , this.node )
    }
    handerClick=()=>{
   
   
       /* 点击卸载容器 */ 
       const state =  ReactDOM.unmountComponentAtNode(this.node)
       console.log(state)
    }
    render(){
   
   
        return <div  style={
   
   {
   
    marginTop:'50px' }}  > 
             <div ref={
   
    ( node ) => this.node = node  }  ></div>  
            <button onClick={
   
    this.handerClick } >click me</button>
        </div>
    }
}

效果

unmounted.gif

本文通过react组件层面,工具层面,hooks层面,react-dom了解了api的用法,希望看完的同学,能够对着文章中的demo自己敲一遍,到头来会发现自己成长不少。

最后, 送人玫瑰,手留余香,觉得有收获的朋友可以给笔者点赞,关注一波 ,陆续更新前端超硬核文章。

提前透漏:接下来会出一部揭秘react事件系统的文章。

感兴趣的同学请关注公众号 前端Sharing 持续推送优质好文

往期react文章

文章中,对于其他没有讲到的react-hooks,建议大家看react-hooks三部曲。

react-hooks三部曲

react进阶系列

react源码系列

开源项目系列

参考文档

react中文文档

相关文章
|
2月前
|
前端开发 JavaScript
深入理解并实践React Hooks —— useEffect与useState
深入理解并实践React Hooks —— useEffect与useState
140 1
|
1月前
|
缓存 测试技术 API
构建高效后端API:实践与哲学
【9月更文挑战第36天】在数字世界的浪潮中,后端API成为了连接用户、数据和业务逻辑的桥梁。本文将深入探讨如何构建一个既高效又灵活的后端API,从设计理念到实际代码实现,带你一探究竟。我们将通过具体示例,展示如何在保证性能的同时,也不失安全性和可维护性。
|
30天前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
149 2
|
1月前
|
缓存 数据挖掘 API
商品详情API接口的应用实践
本文探讨了商品详情API接口在电商领域的应用实践,介绍了其作为高效数据交互方式的重要性,包括实时获取商品信息、提升用户体验和运营效率。文章详细描述了API接口的特点、应用场景如商品展示、SEO优化、数据分析及跨平台整合,并提出了缓存机制、分页加载、异步加载和错误处理等优化策略,旨在全面提升电商运营效果。
|
2月前
|
存储 JSON API
深入解析RESTful API设计原则与实践
【9月更文挑战第21天】在数字化时代,后端开发不仅仅是编写代码那么简单。它关乎于如何高效地连接不同的系统和服务。RESTful API作为一套广泛采用的设计准则,提供了一种优雅的解决方案来简化网络服务的开发。本文将带你深入了解RESTful API的核心设计原则,并通过实际代码示例展示如何将这些原则应用于日常的后端开发工作中。
|
3天前
|
Prometheus 监控 Java
深入探索:自制Agent监控API接口耗时实践
在微服务架构中,监控API接口的调用耗时对于性能优化至关重要。通过监控接口耗时,我们可以识别性能瓶颈,优化服务响应速度。本文将分享如何自己动手实现一个Agent来统计API接口的调用耗时,提供一种实用的技术解决方案。
12 3
|
6天前
|
监控 安全 应用服务中间件
微服务架构下的API网关设计策略与实践####
本文深入探讨了在微服务架构下,API网关作为系统统一入口点的设计策略、实现细节及其在实际应用中的最佳实践。不同于传统的摘要概述,本部分将直接以一段精简的代码示例作为引子,展示一个基于NGINX的简单API网关配置片段,随后引出文章的核心内容,旨在通过具体实例激发读者兴趣,快速理解API网关在微服务架构中的关键作用及实现方式。 ```nginx server { listen 80; server_name api.example.com; location / { proxy_pass http://backend_service:5000;
|
11天前
|
XML API 网络架构
深入理解RESTful API设计原则与实践
【10月更文挑战第26天】在数字化浪潮中,API(应用程序编程接口)成为连接不同软件组件的桥梁。本文将深入浅出地探讨如何根据REST(Representational State Transfer)原则设计高效、易于维护和扩展的API,同时分享一些实用的代码示例,帮助开发者构建更加健壮和用户友好的服务。
|
15天前
|
前端开发 JavaScript
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
手敲Webpack 5:React + TypeScript项目脚手架搭建实践
|
1月前
|
XML JSON API
深入浅出:RESTful API 设计实践与最佳应用
【9月更文挑战第32天】 在数字化时代的浪潮中,RESTful API已成为现代Web服务通信的黄金标准。本文将带您一探究竟,了解如何高效地设计和维护一个清晰、灵活且易于扩展的RESTful API。我们将从基础概念出发,逐步深入到设计原则和最佳实践,最终通过具体案例来展示如何将理论应用于实际开发中。无论您是初学者还是有经验的开发者,这篇文章都将为您提供宝贵的指导和灵感。
下一篇
无影云桌面