「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中文文档

相关文章
|
20天前
|
XML JSON 缓存
深入理解RESTful API设计原则与实践
在现代软件开发中,构建高效、可扩展的应用程序接口(API)是至关重要的。本文旨在探讨RESTful API的核心设计理念,包括其基于HTTP协议的特性,以及如何在实际应用中遵循这些原则来优化API设计。我们将通过具体示例和最佳实践,展示如何创建易于理解、维护且性能优良的RESTful服务,从而提升前后端分离架构下的开发效率和用户体验。
|
15天前
|
机器学习/深度学习 搜索推荐 API
淘宝/天猫按图搜索(拍立淘)API的深度解析与应用实践
在数字化时代,电商行业迅速发展,个性化、便捷性和高效性成为消费者新需求。淘宝/天猫推出的拍立淘API,利用图像识别技术,提供精准的购物搜索体验。本文深入探讨其原理、优势、应用场景及实现方法,助力电商技术和用户体验提升。
|
28天前
|
前端开发 JavaScript API
探究 React Hooks:如何利用全新 API 优化组件逻辑复用与状态管理
本文深入探讨React Hooks的使用方法,通过全新API优化组件逻辑复用和状态管理,提升开发效率和代码可维护性。
|
28天前
|
缓存 API 开发者
构建高效后端服务:RESTful API设计原则与实践
【10月更文挑战第43天】在数字化时代的浪潮中,后端服务的稳定性和效率成为企业竞争力的关键。本文将深入探讨如何构建高效的后端服务,重点介绍RESTful API的设计原则和实践技巧,帮助开发者提升服务的可用性、可扩展性和安全性。通过实际代码示例,我们将展示如何将这些原则应用到日常开发工作中,以确保后端服务能够支撑起现代Web和移动应用的需求。
|
28天前
|
存储 JSON 测试技术
构建高效后端API:实践和原则
【10月更文挑战第43天】本文深入探讨了如何设计和实现高效、可维护的后端API,强调了设计哲学、最佳实践和常见陷阱。通过具体示例,我们展示了如何运用这些原则来提高API的性能和可用性。
|
1月前
|
Prometheus 监控 Java
深入探索:自制Agent监控API接口耗时实践
在微服务架构中,监控API接口的调用耗时对于性能优化至关重要。通过监控接口耗时,我们可以识别性能瓶颈,优化服务响应速度。本文将分享如何自己动手实现一个Agent来统计API接口的调用耗时,提供一种实用的技术解决方案。
43 3
|
14天前
|
监控 搜索推荐 测试技术
电商API的测试与用途:深度解析与实践
在电子商务蓬勃发展的今天,电商API成为连接电商平台、商家、消费者和第三方开发者的重要桥梁。本文深入探讨了电商API的核心功能,包括订单管理、商品管理、用户管理、支付管理和物流管理,并介绍了有效的测试技巧,如理解API文档、设计测试用例、搭建测试环境、自动化测试、压力测试、安全性测试等。文章还详细阐述了电商API的多样化用途,如商品信息获取、订单管理自动化、用户数据管理、库存同步、物流跟踪、支付处理、促销活动管理、评价管理、数据报告和分析、扩展平台功能及跨境电商等,旨在为开发者和电商平台提供有益的参考。
23 0
|
1月前
|
监控 安全 应用服务中间件
微服务架构下的API网关设计策略与实践####
本文深入探讨了在微服务架构下,API网关作为系统统一入口点的设计策略、实现细节及其在实际应用中的最佳实践。不同于传统的摘要概述,本部分将直接以一段精简的代码示例作为引子,展示一个基于NGINX的简单API网关配置片段,随后引出文章的核心内容,旨在通过具体实例激发读者兴趣,快速理解API网关在微服务架构中的关键作用及实现方式。 ```nginx server { listen 80; server_name api.example.com; location / { proxy_pass http://backend_service:5000;
|
1月前
|
XML API 网络架构
深入理解RESTful API设计原则与实践
【10月更文挑战第26天】在数字化浪潮中,API(应用程序编程接口)成为连接不同软件组件的桥梁。本文将深入浅出地探讨如何根据REST(Representational State Transfer)原则设计高效、易于维护和扩展的API,同时分享一些实用的代码示例,帮助开发者构建更加健壮和用户友好的服务。
|
22天前
|
安全 测试技术 API
构建高效RESTful API:后端开发的艺术与实践####
在现代软件开发的浩瀚星空中,RESTful API如同一座桥梁,连接着前端世界的绚丽多彩与后端逻辑的深邃复杂。本文旨在探讨如何精心打造一款既高效又易于维护的RESTful API,通过深入浅出的方式,剖析其设计原则、实现技巧及最佳实践,为后端开发者提供一份实用的指南。我们不深入晦涩的理论,只聚焦于那些能够即刻提升API品质与开发效率的关键点,让你的API在众多服务中脱颖而出。 ####
30 0