聽過哪些與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>

虛擬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、組件通訊:

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;
以上是本次分享,謝謝大家。



