banner
SlhwSR

SlhwSR

热爱技术的一名全栈开发者
github
bilibili

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 (
      <div className="App">
        <Foo />
        <button onClick={() => this.setState({ name: "App" })}>
          Change name
        </button>
      </div>
    );
  }
}

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方法,一旦父組件發生渲染,子組件也會渲染

image

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。