React之render

一、原理

首先,render函数在react中有两种形式:

在类组件中,指的是render方法:

复制代码
class Foo extends React.Component {
    render() {
        return <h1> Foo </h1>;
    }
}

在函数组件中,指的是函数组件本身:

复制代码
function Foo() {
    return <h1> Foo </h1>;
}

render中,我们会编写jsxjsx通过babel编译后就会转化成我们熟悉的js格式,如下:

复制代码
return (
  <div className='cn'>
    <Header> hello </Header>
    <div> start </div>
    Right Reserve
  </div>
)

babel编译后:

复制代码
return (
  React.createElement(
    'div',
    {
      className : 'cn'
    },
    React.createElement(
      Header,
      null,
      'hello'
    ),
    React.createElement(
      'div',
      null,
      'start'
    ),
    'Right Reserve'
  )
)

从名字上来看,createElement方法用来元素的

react中,这个元素就是虚拟DOM树的节点,接收三个参数:

  • type:标签

  • attributes:标签属性,若无则为null

  • children:标签的子节点

这些虚拟DOM树最终会渲染成真实DOM

render过程中,React 将新调用的 render函数返回的树与旧版本的树进行比较,这一步是决定如何更新 DOM 的必要步骤,然后进行 diff 比较,更新 DOM

二、触发时机

render的执行时机主要分成了两部分:

  • 类组件调用 setState 修改状态

    class Foo extends React.Component {
    state = { count: 0 };

    复制代码
    increment = () => {
      const { count } = this.state;
    
      const newCount = count < 10 ? count + 1 : count;
    
      this.setState({ count: newCount });
    };
    
    render() {
      const { count } = this.state;
      console.log("Foo render");
    
      return (
        <div>
          <h1> {count} </h1>
          <button onClick={this.increment}>Increment</button>
        </div>
      );
    }

    }

点击按钮,则调用setState方法,无论count发生变化辩护,控制台都会输出Foo render,证明render执行了

  • 函数组件通过useState hook修改状态

    function Foo() {
    const [count, setCount] = useState(0);

    复制代码
    function increment() {
      const newCount = count < 10 ? count + 1 : count;
      setCount(newCount);
    }
    
    console.log("Foo render");
    
    return (
      <div>
        <h1> {count} </h1>
        <button onClick={increment}>Increment</button>
      </div>
    );

    }

函数组件通过useState这种形式更新数据,当数组的值不发生改变了,就不会触发render

  • 类组件重新渲染

    class App extends React.Component {
    state = { name: "App" };
    render() {
    return (


    <Foo />
    <button onClick={() => this.setState({ name: "App" })}>
    Change name
    </button>

    );
    }
    }

    function Foo() {
    console.log("Foo render");

    复制代码
    return (
      <div>
        <h1> Foo </h1>
      </div>
    );

    }

只要点击了 App 组件内的 Change name 按钮,不管 Foo 具体实现是什么,都会被重新render渲染

  • 函数组件重新渲染

    function App(){
    const [name,setName] = useState('App')

    复制代码
      return (
          <div className="App">
              <Foo />
              <button onClick={() => setName("aaa")}>
                  { name }
              </button>
        </div>
      )

    }

    function Foo() {
    console.log("Foo render");

    复制代码
    return (
      <div>
        <h1> Foo </h1>
      </div>
    );

    }

可以发现,使用useState来更新状态的时候,只有首次会触发Foo render,后面并不会导致Foo render

三、总结

render函数里面可以编写JSX,转化成createElement这种形式,用于生成虚拟DOM,最终转化成真实DOM

React 中,类组件只要执行了 setState 方法,就一定会触发 render 函数执行,函数组件使用useState更改状态不一定导致重新render

组件的props 改变了,不一定触发 render 函数的执行,但是如果 props 的值来自于父组件或者祖先组件的 state

在这种情况下,父组件或者祖先组件的 state 发生了改变,就会导致子组件的重新渲染

所以,一旦执行了setState就会执行render方法,useState 会判断当前值有无发生改变确定是否执行render方法,一旦父组件发生渲染,子组件也会渲染

相关推荐
UXbot9 小时前
AI原型设计工具如何从PRD自动生成交互原型
前端·低代码·ui·交互·ai编程·原型模式
Csvn9 小时前
Vue 最佳实践
前端·vue.js
产品经理爱开发9 小时前
老师用AI开发的HTML教具如何在线托管访问
前端·html·ai编程·持续部署·源代码管理
星恒随风9 小时前
四天学完前端基础三件套(CSS篇)
前端·css·笔记·学习
贫民窟的勇敢爷们10 小时前
Vue项目性能优化的全流程指南
前端·vue.js·性能优化
之歆10 小时前
DAY_25 JavaScript 原型、原型链与值类型/引用类型 ── 深度全解(下)
开发语言·javascript·ecmascript
小短腿的代码世界10 小时前
Qwt实时FFT频谱分析深度解析:从信号采集到可视化渲染的完整架构设计
前端·qt·架构·交互
初见雨夜10 小时前
提测前让 AI 检查一下代码,我的 Bug 率降低了 20%
前端·ai编程
光影少年10 小时前
react的 useState 原理、批量更新机制
前端·react.js·掘金·金石计划
叫我少年10 小时前
Markdown 备忘清单
前端