45、React开发全解析:从基础到实战

React开发全解析:从基础到实战

1. JSX基础

JSX 是一种 JavaScript 的语法扩展,用于在 JavaScript 代码中编写类似 XML 的结构,使代码更简洁易读。

以下是 JSX 的一些基础用法示例:

function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}
function formatName(name) { return `Mr/Mrs ${name}`; }

在这个例子中,如果 user 被传入函数,将返回不同的 React 元素。

1.1 属性定义

在 JSX 代码中定义属性有两种方式:
- 使用引号:

const element = <div id="someDiv"></div>;
  • 使用花括号动态定义值:
function getActiveClass() {
    return 'active';
}
const anotherElement = <div class={getActiveClass()} />;
1.2 元素树创建

JSX 代码还可以创建元素树:

function FullName(props) {
    return (
      <span>{props.givenName} {props.lastName}</span>
    )
}
const element = (
  <div id="root">
    <FullName givenName="Sebastien" lastName="Dubois" />
    <FullName givenName="Alexis" lastName="Georges" />
  </div>
)

上述 React 元素有多个子元素。为了保持代码可读性,我们将 JSX 表达式拆分成多行,并使用括号包围,以避免自动分号插入(ASI)问题。

JSX 的优点还体现在安全性上,嵌入在 JSX 代码中的值会自动进行转义,能有效防止注入攻击。

2. React 元素

JSX 代码会被转译为 React.createElement 函数调用, React.createElement 函数用于创建 React 元素。

以下是前面 JSX 示例转译后的 JavaScript 代码:

function FullName(props) {
  render(React.createElement('span', null, props.givenName, ' ', props.lastName));
}
const element = React.createElement('div', {
  id: 'root'
}, React.createElement(FullName, {
  givenName: 'Sebastien',
  lastName: 'Dubois'
}), React.createElement(FullName, {
  givenName: 'Alexis',
  lastName: 'Georges'
}));

createElement 函数接受三个参数:
- 元素类型
- 作为对象传递的一组 props(稍后详细讨论)
- 子元素(可选)

执行 createElement 函数时,会创建一个具有以下基本结构的对象字面量:

const element = {
  type: 'div',
  props: {
    id: 'root',
    children: [
      {
        type: 'FullName',
        props: {
          givenName: 'Sebastien',
          lastName: 'Dubois',
        },
      },
      { ... }
    ]
  }
};

React 元素是一种描述符,用于创建具有特定状态的组件层次结构,每个 React 元素描述了用户界面的一部分。它不规定如何渲染,渲染工作由渲染器负责。

要渲染元素,可以使用渲染器的 render 函数,例如使用 ReactDOM 将元素渲染到 DOM:

ReactDOM.render(element, document.getElementById('root'));

React 元素是不可变的,更新用户界面意味着创建新元素替换旧元素。由于 React 使用虚拟 DOM,它只会更改最少数量的 DOM 元素,从而提高性能。

以下是一个官方文档的示例:

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}
setInterval(tick, 1000);

在这个示例中,每秒调用 tick 函数时,都需要创建一个新的 React 元素并传递给 ReactDOM render 函数。

3. 组件和 props

React 组件用于将用户界面拆分成小的、可复用的部分。与 Angular 不同,React 组件不需要注册,只需在使用时处于作用域内(即需要在使用前导入或声明)。

概念上,React 组件接受一个不可变的 props 对象作为输入,返回 JSX 或 React.createElement 调用,即 React 元素。

React 组件有两种定义方式:
- 函数组件 :推荐使用,使用纯函数定义。
- 类组件 :继承 React.Component 类并实现 render 方法。

3.1 类组件

类组件在 React 应用中应作为例外情况使用。以下是一个类组件的示例:

const createElement = React.createElement;
class SayHiButton extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            buttonClicked: false,
        };
    }
    render() {
        console.log('Rendering');
        if (this.state.buttonClicked) {
            console.log('The buttonClicked property of the state is true; showing the message');
            return 'Hello from React!';
        }
        return createElement(
            'button',
            {
                onClick: () => {
                    console.log("The button's click handler was clicked. Changing the state of the component");
                    this.setState({
                        buttonClicked: true,
                    }, null)
                }
            },
            'Say hi!' // button's text
        );
    }
}
const domContainer = document.querySelector('#hello-react-container');
ReactDOM.render(createElement(SayHiButton), domContainer);

在这个示例中, SayHiButton 组件根据其内部状态显示不同的消息。类组件和函数组件一样,通过一个 props 对象接收输入,这些属性会传递给构造函数。

以下是另一个使用 JSX 的类组件示例:

export class Foo extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div>Bar</div>
    );
  }
}

从这两个示例可以看出,使用类组件定义方式比较冗长。随着 React 的发展,函数组件变得更强大,应优先使用。

3.2 函数组件

函数组件使用纯函数定义,具有以下优点:
- 更简单易写、易读。
- 代码量更少。
- 稳定、确定性强、可预测且无副作用。
- 易于测试。

以下是一个函数组件的示例:

function DisplayMessage(props) {
  return <div>Welcome to React {props.name}!</div>;
}

在 React 16.8 版本之后,引入了 React hooks,函数组件可以使用组件状态、生命周期方法和 refs 等特性,与类组件基本相当,因此更推荐使用。

4. 对象解构

对象解构是 JavaScript 的一种语法,用于轻松提取对象的部分属性。在编写 React 组件时,对象解构非常有用。

以下是一个简单的对象解构示例:

const myObject = {
    firstName: 'Sebastien',
    age: 36,
    country: 'Belgium',
};
const {firstName, age} = myObject;
console.log(`Firstname: ${firstName}`);

在 React 组件中,如果只有一个输入,可以使用对象解构简化代码:

function DisplayMessage({name}) {
  return <div>Welcome to React {name}!</div>;
}

通过对象解构,我们可以直接使用属性名,而不需要使用 props.

5. 组件状态

创建无状态组件有利于简化和测试,但在某些情况下,组件需要维护自己的内部状态。

在类组件中管理状态的步骤如下:
1. 初始化内部状态对象 :可以通过构造函数或在创建时初始化属性来完成,这是唯一可以直接修改状态的地方。
2. 使用 this.setState 方法修改状态 :在对象构造完成后,需要使用 this.setState 方法来修改状态。

以下是一个类组件管理状态的示例:

import React from 'react';
export class Calculator extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            currentResult: this.props.initialValue,
        };
    }
    render() {
        return (
            <div>
                <span>Current result: {this.state.currentResult}</span>
                <br/>
                <br/>
                <button onClick={() => this.add(1)}>+1</button>
            </div>
        );
    }
    add(value) {
        this.setState((state, props) => {
            return {currentResult: state.currentResult + value}
        });
    }
}

在这个示例中, add 函数展示了如何更新组件状态。 setState 方法的更新是浅合并的,并且 props 和状态更新可能是异步的,因此推荐使用接受函数作为参数的 setState 方法。

组件可以将自己的状态传递给子组件,但仍然负责管理这些值。默认情况下,只要状态或 props 发生变化,React 就会重新渲染组件及其子组件。可以使用 shouldComponentUpdate 方法避免不必要的重新渲染。

6. 提升渲染性能

在前面的示例中,使用内联函数绑定事件处理程序会导致每次组件重新渲染时都创建一个新的函数,这在实际应用中可能会导致性能问题。

更好的方法是定义一次函数并进行绑定:

function onClickHandler() { ... }
...
<button onClick={this.onClickHandler}>+1</button>

总结

本文从 JSX 基础开始,介绍了 React 元素、组件和 props 、对象解构、组件状态以及渲染性能优化等内容。通过学习这些知识,你可以更好地理解和使用 React 进行开发。函数组件由于其简洁性和灵活性,应优先使用。同时,合理管理组件状态和优化渲染性能可以提高应用的性能和可维护性。

流程图

graph TD;
    A[开始] --> B[定义JSX];
    B --> C[转译为React.createElement];
    C --> D[创建React元素];
    D --> E[渲染元素到DOM];
    E --> F[组件和props];
    F --> G[函数组件];
    F --> H[类组件];
    G --> I[使用对象解构];
    H --> J[管理组件状态];
    J --> K[提升渲染性能];
    K --> L[结束];

表格

概念 描述
JSX JavaScript 语法扩展,用于编写类似 XML 的结构
React 元素 React.createElement 创建,是组件层次结构的描述符
组件 将用户界面拆分成小的、可复用的部分
props 组件的输入,不可变
状态 组件的内部数据,可变
函数组件 使用纯函数定义,推荐使用
类组件 继承 React.Component 类,代码冗长
对象解构 用于提取对象的部分属性
渲染性能优化 避免内联函数绑定,提高性能

React开发全解析:从基础到实战

7. 生命周期钩子

在 React 组件的整个生命周期中,会经历挂载、更新和卸载等阶段,生命周期钩子允许我们在这些特定阶段执行代码。

7.1 挂载阶段

挂载阶段是组件首次被创建并插入到 DOM 中的过程。常用的挂载阶段钩子有:
- componentWillMount (已弃用):在组件挂载之前调用。
- render :返回 JSX 或 React.createElement 调用,用于渲染组件。
- componentDidMount :在组件挂载完成后调用,通常用于进行网络请求、订阅事件等操作。

以下是一个简单的示例:

import React from 'react';

class MyComponent extends React.Component {
    componentWillMount() {
        console.log('Component will mount');
    }

    render() {
        return <div>Hello, World!</div>;
    }

    componentDidMount() {
        console.log('Component did mount');
    }
}

export default MyComponent;
7.2 更新阶段

当组件的 props state 发生变化时,会触发更新阶段。常用的更新阶段钩子有:
- componentWillReceiveProps (已弃用):在组件接收到新的 props 时调用。
- shouldComponentUpdate :用于决定组件是否需要更新,可以通过返回 false 来阻止不必要的更新。
- componentWillUpdate (已弃用):在组件更新之前调用。
- render :再次渲染组件。
- componentDidUpdate :在组件更新完成后调用。

以下是一个使用 shouldComponentUpdate 的示例:

import React from 'react';

class MyComponent extends React.Component {
    shouldComponentUpdate(nextProps, nextState) {
        if (this.props.someProp === nextProps.someProp) {
            return false;
        }
        return true;
    }

    render() {
        return <div>{this.props.someProp}</div>;
    }
}

export default MyComponent;
7.3 卸载阶段

卸载阶段是组件从 DOM 中移除的过程。常用的卸载阶段钩子有:
- componentWillUnmount :在组件卸载之前调用,通常用于清理定时器、取消订阅等操作。

以下是一个示例:

import React from 'react';

class MyComponent extends React.Component {
    componentDidMount() {
        this.timer = setInterval(() => {
            console.log('Timer running');
        }, 1000);
    }

    componentWillUnmount() {
        clearInterval(this.timer);
        console.log('Component will unmount');
    }

    render() {
        return <div>Hello, World!</div>;
    }
}

export default MyComponent;
8. React Hooks

React Hooks 是 React 16.8 引入的新特性,它允许我们在不编写 class 的情况下使用 state 以及其他 React 特性。

8.1 useState

useState 用于在函数组件中添加 state 。它返回一个数组,第一个元素是当前的 state 值,第二个元素是更新 state 的函数。

以下是一个使用 useState 的示例:

import React, { useState } from 'react';

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

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
        </div>
    );
}

export default Counter;
8.2 useEffect

useEffect 用于在函数组件中执行副作用操作,例如数据获取、订阅事件等。它接受一个函数作为参数,该函数会在组件渲染后执行。

以下是一个使用 useEffect 的示例:

import React, { useState, useEffect } from 'react';

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

    useEffect(() => {
        document.title = `You clicked ${count} times`;
    }, [count]);

    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
            </button>
        </div>
    );
}

export default Example;
8.3 自定义 Hooks

我们还可以创建自定义 Hooks 来复用逻辑。以下是一个自定义 Hooks 的示例:

import React, { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
    const [isOnline, setIsOnline] = useState(null);

    useEffect(() => {
        function handleStatusChange(status) {
            setIsOnline(status.isOnline);
        }

        ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
        return () => {
            ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
        };
    }, [friendID]);

    return isOnline;
}
9. 高阶组件

高阶组件(Higher-Order Component,简称 HOC)是一个函数,它接受一个组件作为参数,并返回一个新的组件。高阶组件用于代码复用、状态管理等。

以下是一个简单的高阶组件示例:

import React from 'react';

function withLogging(WrappedComponent) {
    return class extends React.Component {
        componentDidMount() {
            console.log('Component mounted');
        }

        render() {
            return <WrappedComponent {...this.props} />;
        }
    };
}

class MyComponent extends React.Component {
    render() {
        return <div>Hello, World!</div>;
    }
}

const LoggedComponent = withLogging(MyComponent);
10. 性能优化策略总结

为了提高 React 应用的性能,我们可以采取以下策略:
1. 使用 React.memo :对于函数组件,使用 React.memo 可以对组件进行浅比较,避免不必要的渲染。

import React from 'react';

const MyComponent = React.memo(function MyComponent(props) {
    return <div>{props.someProp}</div>;
});
  1. 使用 shouldComponentUpdate :对于类组件,使用 shouldComponentUpdate 方法来控制组件是否需要更新。
  2. 避免内联函数 :内联函数会导致每次渲染时都创建新的函数,使用绑定函数可以避免这个问题。
  3. 使用 React.lazy 和 Suspense :对于大型应用,可以使用 React.lazy Suspense 实现代码分割,提高加载速度。
import React, { lazy, Suspense } from 'react';

const LazyComponent = lazy(() => import('./LazyComponent'));

function App() {
    return (
        <div>
            <Suspense fallback={<div>Loading...</div>}>
                <LazyComponent />
            </Suspense>
        </div>
    );
}

流程图

graph TD;
    A[组件挂载] --> B[componentWillMount];
    B --> C[render];
    C --> D[componentDidMount];
    D --> E[组件更新];
    E --> F[componentWillReceiveProps];
    F --> G[shouldComponentUpdate];
    G -->|true| H[componentWillUpdate];
    H --> I[render];
    I --> J[componentDidUpdate];
    J --> K[组件卸载];
    K --> L[componentWillUnmount];
    G -->|false| M[不更新];

表格

生命周期钩子 阶段 描述
componentWillMount 挂载 在组件挂载之前调用(已弃用)
render 挂载、更新 返回 JSX 或 React.createElement 调用
componentDidMount 挂载 在组件挂载完成后调用
componentWillReceiveProps 更新 在组件接收到新的 props 时调用(已弃用)
shouldComponentUpdate 更新 决定组件是否需要更新
componentWillUpdate 更新 在组件更新之前调用(已弃用)
componentDidUpdate 更新 在组件更新完成后调用
componentWillUnmount 卸载 在组件卸载之前调用

总结

本文进一步深入介绍了 React 的生命周期钩子、React Hooks、高阶组件以及性能优化策略。生命周期钩子让我们可以在组件的不同阶段执行特定代码,React Hooks 使函数组件能够使用更多特性,高阶组件则用于代码复用。同时,合理运用性能优化策略可以显著提高 React 应用的性能和响应速度。通过掌握这些知识,你可以更加熟练地使用 React 进行复杂应用的开发。

演示了为无线无人机电池充电设计的感应电力传输(IPT)系统 Dynamic Wireless Charging for (UAV) using Inductive Coupling 模拟了为无人机(UAV)量身定制的无线电力传输(WPT)系统。该模型演示了直流电到高频交流电的转换,通过磁共振在气隙中无线传输能量,以及整流回直流电用于电池充电。 系统拓扑包括: 输入级:使用IGBT/二极管开关连接到桥逆变器的直流电压源(12V)。 开关控制:脉冲发生器以85 kHz(周期:1/85000秒)的开关频率运行,这是SAE J2954无线充电标准的标准频率。 耦合级:使用互感和线性变压器块来模拟具有特定耦合系数的发射(Tx)和接收(Rx)线圈。 补偿:包括串联RLC分支,用于模拟谐振补偿网络(将线圈调谐到谐振频率)。 输出级:桥式整流器(基于二极管),用于将高频交流电转换回直流电,以供负载使用。 仪器:使用示波器块进行面的电压和电流测量,用于分析输入/输出波形和效率。 模拟详细信息: 求解器:离散Tustin/向后Euler(通过powergui)。 采样时间:50e-6秒。 4.主要特点 高频逆变:模拟85 kHz下IGBT的开关瞬态。 磁耦合:模拟无人机着陆垫和机载接收器之间的松耦合行为。 Power GUI集成:用于专用电力系统离散仿真的设置。 波形分析:预配置的范围,用于查看逆变器输出电压、初级/次级电流和整流直流电压。 5.安装与使用 确保您已安装MATLAB和Simulink。 所需工具箱:必须安装Simscape Electrical(以前称为SimPowerSystems)工具箱才能运行sps_lib块。 打开文件并运行模拟。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值