React初印象

聽過哪些與React相關(guān)的名詞:


dom5.png

今天主要介紹:React 18.3
以下分享源碼在此

1、虛擬 DOM(Virtual DOM):

React 使用虛擬 DOM 渲染流程。


dom1.png
 <body>
  <div id="root"></div>
  <!-- 引入React.js -->
  <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
  <!-- 引入ReactDOM.js -->
  <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>

  <script src="https://unpkg.com/babel-standalone/babel.min.js"></script>

  <script type="text/babel">

    function handleClick() {
      alert('Div element clicked!');
    }

     //React.createElement是React官方提供創(chuàng)建虛擬dom的一個api.
    const element = React.createElement(
      'div',
      { className: 'redBg', onClick: handleClick },
      'Item 1'
    );

//JSX語法,經(jīng)過Babel編譯器,轉(zhuǎn)化成React.createElement()
   const element2 = (
      <div className="redBg" onClick={handleClick}>
        Item 1
      </div>
    );

    //將虛擬 DOM(React 元素)渲染到真實 DOM 的過程: 1.獲取頁面元素-->2.創(chuàng)建容器-->3.將虛擬元素渲染到容器內(nèi)

    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(element);

    const realDom = document.getElementById('realDom');

    console.log('virtualDom', element);
    console.log('realDom', realDom);

  </script>
</body>
dom3.png
虛擬dom總結(jié):
- 本質(zhì):JS對象,相對真實dom,相對真實dom是一個輕量級的對象。

- 優(yōu)點:
1、最小化真實dom操作,減少重繪(Repaint)和重排(Reflow)次數(shù)。

   重排:受DOM的布局、尺寸、位置等發(fā)生變化時影響
   重繪:受DOM的外觀(如顏色、邊框、背景)發(fā)生變化時影響

2、快速開發(fā),組件復(fù)用。

- 缺點:多一份虛擬dom內(nèi)存開銷。

2、JSX:

JSX是一種用于描述 UI 的JavaScript 語法擴展,允許在 JavaScript 中編寫類似 HTML 的代碼。
編譯器Babel將jsx代碼編譯成React.createElement。


dom4.png
  • 單行寫法
const element = <h1>Hello, world!</h1>;
  • 多行寫法

const element2 = (
    <div className="redBg" onClick={handleClick}>
        muplti line
      </div>
   );
  • 傳參,可用插入表達(dá)式
const itemName = 'Item 2';
const element3 = (
    <div className="redBg" onClick={handleClick}>
        {itemName}
      </div>
   );
  • 復(fù)雜點的寫法,多寫點JS方法
const items = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry'];
const element = (
  <div className="fruit-list">
    <h1>Fruit List</h1>
    <ul>
      {items.map((item, index) => (
        <li key={index} className="fruit-item">
          {item}
        </li>
      ))}
    </ul>
    <footer>
      <p>Total items: {items.length}</p>
    </footer>
  </div>
);
// 渲染到頁面
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(element);
  • 根元素
    如何不增加額外 DOM 節(jié)點
錯誤寫法:
const element = (
    <h1>Hello</h1>
    <p>This is a paragraph.</p>
   );
糾正寫法:
const element = (
  <React.Fragment>
    <h1>Hello</h1>
    <p>This is a paragraph.</p>
  </React.Fragment>
);
簡易寫法:
const element = (
  <React.Fragment>
    <h1>Hello</h1>
    <p>This is a paragraph.</p>
  </React.Fragment>
);
總結(jié):
<> ... </> = <React.Fragment>... </React.Fragment>

而在angular中,剛好相反,是在HTML 的代碼編寫js代碼

<div>
  <p>{{ message }}</p>
  <button (click)="updateMessage()">Click me</button>
</div>

3、組件(Component):

React 的核心概念,UI 的構(gòu)建塊。組件可以是函數(shù)組件或類組件

  • 類組件
class ClassComponent extends Component {
    constructor(props) {
        super(props);
        // 初始化 state
        this.state = {
            count: 0,
        };
    }

    componentDidMount() {
        // 組件掛載后調(diào)用
        console.log('Component did mount');
    }

    shouldComponentUpdate(nextProps, nextState) {
        // 控制組件是否需要重新渲染
        return nextState.count !== this.state.count;
    }

    componentDidUpdate(prevProps, prevState) {
        // 組件更新后調(diào)用
        console.log('Component did update');
    }

    componentWillUnmount() {
        // 組件卸載之前調(diào)用
        console.log('Component will unmount');
    }

    render() {
        return (
            <div>
                <p>Count: {this.state.count}</p>
                <button onClick={this.handleClick}>Increment</button>
            </div>
        );
    }
}

ClassComponent.propTypes = {
    name: PropTypes.string.isRequired,
    age: PropTypes.number,
    onValueChange: PropTypes.func,
};

export default ClassComponent;
  • 函數(shù)組件
import React from 'react'
import './Style.css';
function FCComponent() {
  return (
    <div className='bg-yellow center'>這是函數(shù)組件</div>
  )
}

export default FCComponent

3、狀態(tài)(State):

1.是組件內(nèi)部的狀態(tài)。
2.可變,通常在組件內(nèi)部管理和更新。
3.用于管理組件自身的數(shù)據(jù)和狀態(tài)。

  • 類組件的state
constructor(props) {
    super(props);
    // 初始化 state
    this.state = {
          count: 0,
           name: '',
           age: 0
        };
}
  • 函數(shù)組件的state
const [count, setCount] = useState(0);
const [name, setName] = useState('');
const [age, setAge] = useState(0);

4、屬性(Props):

1.是組件的屬性,用于從父組件傳遞數(shù)據(jù)和回調(diào)函數(shù)。
2.不可變,子組件不能直接修改。
3.用于將數(shù)據(jù)和功能從父組件傳遞到子組件。

function Welcome(props) {
  return <h1>Hello, {props.name}!</h1>;
}

5、生命周期方法(Lifecycle Methods):

類組件中特定的鉤子函數(shù),用于在組件的不同階段執(zhí)行代碼,如 componentDidMount、componentDidUpdate 和 componentWillUnmount。

class ComponentA extends Component {
  constructor(props) {
    super(props);
    this.state = {
      // 初始化 state
    };
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    // 用于根據(jù)新的 props 更新 state
    return null;
  }

  componentDidMount() {
    // 組件掛載后調(diào)用
  }

  shouldComponentUpdate(nextProps, nextState) {
    // 控制組件是否需要重新渲染
    return true;
  }

  static getSnapshotBeforeUpdate(prevProps, prevState) {
    // 在更新之前獲取快照
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // 組件更新后調(diào)用
  }

  componentWillUnmount() {
    // 組件卸載之前調(diào)用
  }

  render() {
    return (
      <div>
        {/* 組件內(nèi)容 */}
      </div>
    );
  }
}
ComponentA .propTypes = {
  // 定義 prop 類型
};

export default Second;

6、Hooks:

React 16.8 引入的特性,允許在函數(shù)組件中使用狀態(tài)和其他 React 特性,如 useState 和 useEffect。


dom6.png

7、組件通訊:

dom7.png
pubsub使用:
安裝
(1) npm install pubsub-js --save
導(dǎo)入
(2) import PubSub from "pubsub-js"

class Publisher extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        num: 0
      };
    }
    componentDidMount() {  
      // 假設(shè)我們在組件掛載后發(fā)布一個事件
      setInterval(() => {
        PubSub.publish('someChannel', { message: 'Hello from Publisher!'+ this.state.num }); 
        this.setState({
          num: this.state.num + 1
        });
  
      }, 1000);
    } 
    
    render() {  
      return <div>Publisher Component</div>;  
    }  
  }  
    
  class Subscriber extends React.Component {  
    componentDidMount() {  
      // 訂閱事件  
      this.token = PubSub.subscribe('someChannel', (msg, data) => {  
        console.log(data.message, msg); // 輸出: Hello from Publisher!  
      });  
    }  
    
    componentWillUnmount() {  
      // 組件卸載時取消訂閱,防止內(nèi)存泄漏  
      PubSub.unsubscribe(this.token);
    }  
    
    render() {  
      return <div>Subscriber Component</div>;  
    }  
  }  

8、上下文(Context):

用于在組件樹中傳遞數(shù)據(jù),而不需要通過每層組件手動傳遞 props

import React, { createContext, Component } from 'react';

// 創(chuàng)建一個 Context 對象
const MyContext = createContext();

// 創(chuàng)建一個提供 Context 的組件
class MyProvider extends Component {
    state = {
        user: {
            name: 'Alice',
            age: 30
        }
    };

    setUser = (name, age) => {
        this.setState({
            user: { name, age }
        });
    };

    render() {
        return (
            <MyContext.Provider value={{ 
                user: this.state.user,
                setUser: this.setUser
            }}>
                {this.props.children}
            </MyContext.Provider>
        );
    }
}
import React, { Component } from 'react';

// 創(chuàng)建一個消費 Context 的組件
class ChildComponent extends Component {
    static contextType = MyContext;

    handleChangeUser = () => {
        const { setUser } = this.context;
        setUser('Bob', 25);
    };

    render() {
        const { user } = this.context;
        return (
            <div>
                <p>User Name: {user.name}</p>
                <p>User Age: {user.age}</p>
                <button onClick={this.handleChangeUser}>Change User</button>
            </div>
        );
    }
}

// 創(chuàng)建一個消費 Context 的組件
class Child2Component extends Component {
    static contextType = MyContext;

    handleChangeUser = () => {
        const { setUser } = this.context;
        setUser('Bob--22', 250);
    };

    render() {
        const { user } = this.context;
        return (
            <div>
                <p>User Name: {user.name}</p>
                <p>User Age: {user.age}</p>
                <button onClick={this.handleChangeUser}>Change User</button>
            </div>
        );
    }
}

// 創(chuàng)建一個頂層父組件
class ParentContextComponent extends Component {
    render() {
        return (
            <MyProvider>
                <div className='center'>
                    <h1>上下文Context Component</h1>
                    <ChildComponent />
                    <br/>
                    <Child2Component />
                </div>
            </MyProvider>
        );
    }
}

export default ParentContextComponent;

9、Redux:

一個流行的狀態(tài)管理庫,常與 React 一起使用,幫助管理應(yīng)用的全局狀態(tài)。
由于內(nèi)容比較多,下次再專門做個分享會。

10、插槽:

先來看一段angular的代碼

先定義一個包含插槽的組件container.component:

<div class="parent">
  <h1>Parent Component</h1>
  <!-- 第一個插槽 -->
  <ng-content select="[header]"></ng-content>
  <hr/>
  <!-- 第二個插槽 -->
  <ng-content select="[body]"></ng-content>
  <hr/>
  <!-- 第三個插槽 -->
  <ng-content select="[footer]"></ng-content>
</div>

調(diào)用container.component,插入需要不同位置的代碼

<!-- app.component.html -->
<app-parent>
  <div header>
    <h2>This is the Header Content</h2>
  </div>
  <div body>
    <p>This is the Body Content</p>
  </div>
  <div footer>
    <p>This is the Footer Content</p>
  </div>
</app-parent>
下面再看一下React的代碼

先定義一個包含插槽的組件container.component:

import React, { Component } from 'react';

class ParentComponent extends Component {
  render() {
    const { header, body, footer } = this.props;
    return (
      <div className="parent">
        <h1>Parent Component</h1>
        {/* 渲染不同的插槽內(nèi)容 */}
        <div className="header">{header}</div>
        <hr/>
        <div className="body">{body}</div>
        <hr/>
        <div className="footer">{footer}</div>
      </div>
    );
  }
}

export default ParentComponent;

將內(nèi)容作為 props 傳遞給 ParentComponent 的不同插槽

import React, { Component } from 'react';
import ParentComponent from './ParentComponent';

class App extends Component {
  render() {
    return (
      <ParentComponent
        header={<h2>This is the Header Content</h2>}
        body={<p>This is the Body Content</p>}
        footer={<p>This is the Footer Content</p>}
      />
    );
  }
}

export default App;

以上是本次分享,謝謝大家。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容