快速掌握 React 基础入门: 一个完整的指南(二)

简介: 快速掌握 React 基础入门: 一个完整的指南

快速掌握 React 基础入门: 一个完整的指南(一)https://developer.aliyun.com/article/1426132


D. JSX 中的表达式

在 JSX 中,可以通过花括号 {} 来引用 JavaScript 表达式,从而可以动态渲染组件内容。

例如,我们可以通过引用一个变量来动态显示一个组件的内容:

import React from 'react';
function Greeting(props) {
  const name = props.name;
  return <div>Hello, {name}!</div>;
}
function App() {
  const name = 'Alice';
  return <Greeting name={name} />;
}
export default App;

在这个示例中,Greeting 组件接收一个 name 属性,将其插入到字符串中来动态生成问候语。而在 App 组件中,我们定义了一个名为 name 的变量,并将其作为 Greeting 组件的 name 属性进行传递。

在 JSX 中,我们可以在花括号中使用任意的 JavaScript 表达式,例如:

import React from 'react';
function Greeting(props) {
   return <div>{props.isActive ? 'This user is active' : 'This user is not active'}</div>;
}
function App() {
  const isActive = true;
  return <Greeting isActive={isActive} />;
}
export default App;

在这个示例中,我们使用一个带有三目运算符的 JavaScript 表达式来动态地渲染 Greeting 组件中的内容,根据传入的 isActive 属性来判断当前用户是否处于活跃状态。

需要注意的是,在 JSX 中,只能引用 JavaScript 表达式,而不能引用语句或代码块。因此,不能在花括号中使用诸如 ifforswitch 等控制流语句,只能使用简单的表达式或函数调用来完成相应的逻辑。

V. State 和 Props

A. 概述

React 中有两种常用的数据流:propsstate

Props组件之间通信的一种方式,是从父组件向子组件传递数据的方式。

props只读的,不能在组件内部修改。父组件可以随时更改 props 的值,因此,它是一种“单向数据流”的模式,即数据从上层组件流向下层组件。

例如,我们可以通过 props 来传递一些参数或回调函数给子组件,从而控制子组件的行为和显示:

import React from 'react';
function ChildComponent(props) {
  return (
    <div>
      <p>{props.title}</p>
      <button onClick={props.onClick}>Click me</button>
    </div>
  );
}
function ParentComponent(props) {
  function handleClick() {
    console.log('Button clicked!');
  }
  return <ChildComponent title="Hello World!" onClick={handleClick} />;
}
export default ParentComponent;

在这个示例中,我们将一个名为 title 的字符串和一个名为 onClick 的回调函数作为 props 传递给了子组件 ChildComponent,从而控制子组件的标题和按钮行为。

State 则是组件内部自身管理的一种数据。它能够让组件根据不同的外部条件渲染出不同的结果。和 props 不同,state 可以在组件内部修改,并且修改 state 会重新渲染组件。在 React 组件中,每当 state 或 props 发生变化时,React 会自动重新渲染组件。

例如,我们可以使用 state 来控制组件在不同的状态下渲染不同的结果:

import React, { useState } from 'react';
function MyComponent(props) {
  const [isActive, setIsActive] = useState(false);
  function handleClick() {
    setIsActive(!isActive);
  }
  return (
    <div>
      <p>{props.title}</p>
      <button onClick={handleClick}>
        {isActive ? 'Active' : 'Not Active'}
      </button>
    </div>
  );
}
export default MyComponent;

在这个示例中,我们定义了一个名为 isActive 的 state,并在按钮的点击事件中修改它的值来控制按钮显示内容的变化。当我们点击按钮时,组件的 state 发生变化,React 会自动重新渲染组件,从而实现按钮内容的切换。

总体来说,props 和 state 是 React 组件中最常用的两种数据流,它们在组件之间和组件内部分别扮演着不同的角色,帮助我们实现复杂的前端功能。

B. State

在 React 中,state 表示组件内部的状态。每个组件都可以定义自己的 state,并根据 state 的值来渲染 UI 界面。如果某个组件的 state 发生了变化,React 会自动重新渲染组件,并将新的 state 值传递给组件重新渲染。

在类组件中,我们可以通过定义构造函数来初始化组件的 state,例如:

import React, { Component } from 'react';
class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }
  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Increment
        </button>
      </div>
    );
  }
}
export default MyComponent;

在这个示例中,我们定义了一个名为 count 的 state,初始值为 0,在组件的 render 方法中用来渲染计数器和按钮。当我们点击按钮时,会调用 setState 方法来修改 state 值,从而触发组件的重新渲染。

需要注意的是,在 React 中,不要直接修改 state 的值,而是应该使用 setState 方法来修改 state。因为 setState 方法不仅会更新 state,还会触发组件重新渲染,从而保证 UI 的一致性。

另外,由于 state 只能在类组件中使用,如果我们需要在函数式组件中管理状态,可以使用 useState 钩子函数来定义 state,例如:

import React, { useState } from 'react';
function MyComponent(props) {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
export default MyComponent;

在这个示例中,我们使用 useState 钩子函数来声明名为 count 的 state,初始值为 0,通过调用 setCount 方法来修改 state 值。这样,就可以在函数式组件中管理组件的状态了。

C. Props

在 React 中,props 是一种用来传递数据的机制,用途类似于参数传递。通过 props,我们可以将父组件的数据传递给子组件,从而实现组件之间的通信。

在函数组件中,props 是函数的参数,例如:

import React from 'react';
function MyComponent(props) {
  return <div>{props.message}</div>;
}
export default MyComponent;

在这个示例中,我们定义了一个名为 message 的 props,并在组件中使用它来渲染文本。当我们在父组件中使用 时,传递给子组件的 props 中就包含了一个名为 message,值为 “Hello World” 的属性。

在类组件中,我们可以通过 this.props 来访问成员变量,例如:

import React, { Component } from 'react';
class MyComponent extends Component {
  render() {
    return <div>{this.props.message}</div>;
  }
}
export default MyComponent;

这里的 this.props 是一个对象,包含了传递给组件的所有 props 属性。我们可以通过 this.props 来访问这些属性,并在组件中使用它们来渲染 UI。

需要注意的是,props 是只读的,不应该在子组件中直接修改 props 的值。如果需要修改组件的状态,应该定义自己的 state,并通过回调函数来实现从父组件向子组件传递数据。

例如,我们可以通过定义一个回调函数 onButtonClick 来向父组件传递按钮点击事件的信息:

import React, { Component } from 'react';
class MyComponent extends Component {
  handleClick = () => {
    this.props.onButtonClick('Button clicked!');
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click me</button>
      </div>
    );
  }
}
export default MyComponent;

在这个示例中,我们定义了一个名为 onButtonClick 的回调函数,并在按钮的点击事件中调用它来向父组件传递信息。父组件可以通过传递一个回调函数来接收这个信息:

import React, { Component } from 'react';
import MyComponent from './MyComponent';
class App extends Component {
  handleButtonClick = (message) => {
    console.log(message);
  }
  render() {
    return (
      <div>
        <MyComponent onButtonClick={this.handleButtonClick} />
      </div>
    );
  }
}
export default App;

在这个示例中,我们在父组件中定义了一个名为 handleButtonClick 的回调函数,并将它作为 onButtonClick 属性传递给了子组件 MyComponent。当子组件的按钮被点击时,它会调用 onButtonClick 方法,并将消息传递给父组件。父组件接收到消息后,可以在控制台中输出这个消息。

VI. 事件处理

A. 事件绑定

在 React 中,事件绑定和处理与传统的 HTML 相比有些不同。这是因为在 React 中,事件处理是基于虚拟 DOM 实现的,需要在组件中定义事件处理器,并将它们绑定到 UI 元素上。

在 React 中,我们可以使用 onClickonMouseOveronChange 等事件绑定函数来绑定事件,例如:

import React, { Component } from 'react';
class MyComponent extends Component {
  handleClick = () => {
    console.log('Button clicked!');
  }
  handleMouseOver = () => {
    console.log('Mouse over!');
  }
  handleChange = (event) => {
    console.log('Input value:', event.target.value);
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick} onMouseOver={this.handleMouseOver}>Click me</button>
        <input type="text" onChange={this.handleChange} />
      </div>
    );
  }
}
export default MyComponent;

在这个示例中,我们定义了三个名为 handleClickhandleMouseOverhandleChange 的事件处理函数,并将它们绑定到了按钮和输入框上。当按钮被点击、鼠标经过或输入框的值发生变化时,相应的事件处理函数就会被触发。

需要注意的是,在事件处理函数中不能使用 this 来访问组件的成员变量,因为事件处理函数默认是在全局作用域下执行的,this 指向全局对象。如果需要访问组件的成员变量,可以将事件处理函数定义为箭头函数或使用 bind 方法绑定 this 指向。

例如,这里我们使用箭头函数来定义事件处理函数:

import React, { Component } from 'react';
class MyComponent extends Component {
  state = { count: 0 };
  handleClick = () => {
    this.setState({ count: this.state.count + 1 });
  }
  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.handleClick}>Increment</button>
      </div>
    );
  }
}
export default MyComponent;

在这个示例中,我们定义了一个名为 count 的 state,并在按钮的点击事件中使用箭头函数来修改 state 值。这样,就可以在事件处理函数中访问组件的成员变量了。

B. 事件对象

事件处理函数的参数中会自动传入一个 event(也可以自定义名称)事件对象,用它可以获取触发事件的相关信息,如 targetcurrentTargetclientX 等等。

  • event.target:获取触发事件的元素,即事件的发出者。比如 button 或者 div 等。
  • event.currentTarget:获取所有被绑定事件的元素,即事件绑定的发生元素。比如事件被绑定在 div 上,那么 currentTarget 获取的是这个 div
  • event.preventDefault():阻止默认行为,例如禁止某个元素的链接跳转或表单提交。
  • event.stopPropagation():停止事件冒泡,即当某个元素上触发事件时,该事件不会向上层的元素进一步传播。

示例:

import React from 'react';
function MyComponent() {
  function handleClick(e) {
    console.log(e.target);
    console.log(e.currentTarget);
    e.preventDefault();
    e.stopPropagation();
  }
  return (
    <div>
      <a href="https://google.com" onClick={handleClick}>
        Click me
      </a>
      <button onClick={handleClick}>Button</button>
    </div>
  );
}
export default MyComponent;

在这个例子中,我们定义了一个名为 handleClick 的事件处理函数,并将它绑定到两个 UI 元素(abutton)的点击事件上。当用户点击这两个元素时,会触发 handleClick 方法,并传入一个名为 e 的事件对象。我们可以使用 e.targete.currentTarget 来获取触发事件的元素和绑定事件的元素,并使用 e.preventDefault()e.stopPropagation() 阻止默认行为和事件冒泡。

C. setState

setState 是 React 中一个非常常用的方法,用来更新组件的状态。

在类组件中,setStateComponent 类的一个成员函数,通过调用 setState 方法,我们可以更新组件的状态,并触发组件的重新渲染。

setState 有两种使用方式:

  • 第一种是传入一个对象,用来更新部分状态,例如:
this.setState({ count: this.state.count + 1 });
  • 在这个例子中,我们使用 setState 方法来更新 count 状态,将它的值增加 1。通过传入一个对象,我们可以只更新部分状态,而不必更新整个状态对象。
  • 第二种是传入一个函数,函数的第一个参数是前一个状态,返回一个对象,用来更新状态,例如:
this.setState((prevState) => ({ count: prevState.count + 1 }));
  • 在这个例子中,我们使用函数作为 setState 的参数,传入一个名为 prevState 的参数,表示前一个状态对象。函数返回一个对象,用来更新状态。通过传入一个函数,我们可以避免出现更新时的竞态条件(race condition)。

需要注意的是,由于 setState 是异步的,因此如果在 setState 中读取 this.state 的值,可能会得到不准确的结果。如果需要在 setState 后执行一些操作,可以将操作放入 setState 的第二个参数中,例如:

this.setState({ count: this.state.count + 1 }, () => {
  console.log('Count updated to:', this.state.count);
});

在这个例子中,我们将一条输出语句放入 setState 的第二个参数中,当状态更新完成后,输出语句就会被执行。

另外,由于 setState 的机制是异步的,如果我们需要在多个状态更新操作完成后才执行一些操作,可以使用 componentDidUpdate 生命周期函数来处理。在 componentDidUpdate 中可以检查当前状态是否符合预期,并执行一些操作。

VII. 生命周期

A. 概述

在 React 组件中,有许多生命周期函数可以用来在不同的时间点执行各种操作。生命周期函数可以帮助我们在组件的不同阶段进行一些初始化、渲染、更新、卸载等操作,控制整个组件的行为和外部交互。

React 组件的生命周期可以分为三个阶段:

  1. 挂载阶段(Mounting):组件实例被创建,插入到 DOM 中,完成了组件的第一次渲染。
  2. 更新阶段(Updating):组件被重新渲染,可能由于 props 或 state 发生改变产生更新,也可能由于 forceUpdate() 触发更新。
  3. 卸载阶段(Unmounting):组件从 DOM 中移除,销毁组件实例,释放相关资源。

在每个阶段,React 会自动调用相应的生命周期函数,我们可以在这些函数中实现特定的操作。

具体来说,React 组件的生命周期函数包括以下函数:

  1. constructor(props):构造函数,用来初始化组件的状态和绑定成员函数的 this 指向。
  2. getDerivedStateFromProps(props, state):静态函数,用来更新组件状态,返回新的 state 对象或 null。通常用来在 props 发生变化时更新 state。
  3. render():渲染函数,用来生成组件的虚拟 DOM。
  4. componentDidMount():挂载函数,用来进行组件的初始化操作,例如网络请求、定时器等。
  5. shouldComponentUpdate(nextProps, nextState):更新函数,用来判断组件是否需要更新。返回一个布尔值,表示是否需要更新。默认返回 true,即总是更新。
  6. getSnapshotBeforeUpdate(prevProps, prevState):静态函数,用来获取更新前的 DOM 快照。返回一个快照对象或 null。通常用来在组件更新前保存一些 DOM 状态,并在更新后恢复状态。
  7. componentDidUpdate(prevProps, prevState, snapshot):更新函数,用来进行组件更新后的操作,例如重新计算 DOM 元素的位置、滚动条位置等。
  8. componentWillUnmount():卸载函数,用来进行组件的清理操作,例如取消订阅、清除定时器等。

还有一些其他的生命周期函数,不过它们有些是过去时态,已经废弃或者不建议使用了,如componentWillMount(), componentWillReceiveProps() 等。

B. Mounting 阶段

Mounting 阶段是指 React 组件被实例化,并将组件的虚拟 DOM 渲染到实际的 DOM 中的过程。

在 Mounting 阶段,React 会自动调用以下生命周期函数(按照调用顺序):

  1. constructor(props):构造函数,在此函数中可以初始化组件的状态。
  2. static getDerivedStateFromProps(props, state):静态函数,该函数会在虚拟 DOM 处理之前被调用,用于更新组件的状态。通常情况下,推荐根据传入的 props 来更新组件的 state,并返回更新后的 state。如果不需要更新状态,则返回 null
  3. render():渲染函数,返回组件的虚拟 DOM,用来显示在页面上。
  4. componentDidMount():挂载函数,组件被挂载到实际的 DOM 树上后调用,此时可以进行一些网络请求、订阅事件等操作。

示例代码:

import React, { Component } from 'react';
class Example extends Component {
  constructor(props) {
    super(props);
    this.state = { value: 'Hello World' };
  }
  static getDerivedStateFromProps(props, state) {
    console.log('getDerivedStateFromProps', props, state);
    return null;
  }
  componentDidMount() {
    console.log('componentDidMount');
  }
  render() {
    console.log('render');
    return (
      <div>
        <p>{this.state.value}</p>
      </div>
    );
  }
}
export default Example;

在这个例子中,我们定义了一个名为 Example 的组件,并在其中实现了 constructorgetDerivedStateFromPropscomponentDidMount 以及 render 函数。在 constructor 中,我们初始化了组件的 state,并在 render 函数中将 state 的值显示在了页面上。在 getDerivedStateFromPropscomponentDidMount 函数中,我们分别输出了一些信息,用于演示生命周期函数的调用顺序。

当使用 Example 组件创建实例时,React 首先会调用 constructor 构造函数,然后调用 getDerivedStateFromProps 静态函数,返回 null。接着,React 调用 render 函数,生成了组件的虚拟 DOM,并显示在页面上。最后,React 调用 componentDidMount 函数,此时组件已经被挂载到实际的 DOM 树上,可以进行一些初始化的操作。


快速掌握 React 基础入门: 一个完整的指南(三)https://developer.aliyun.com/article/1426134

相关文章
|
1月前
|
前端开发 JavaScript 开发者
React:JSX语法入门
React:JSX语法入门
36 0
|
1月前
|
前端开发 JavaScript
React Hooks 入门基础(详细使用)
React Hooks 入门基础(详细使用)
32 0
|
15天前
|
前端开发
前端react入门day02-React中的事件绑定与组件
前端react入门day02-React中的事件绑定与组件
|
1月前
|
前端开发 JavaScript 索引
快速掌握 React 基础入门: 一个完整的指南(三)
快速掌握 React 基础入门: 一个完整的指南
|
1月前
|
前端开发 JavaScript Linux
快速掌握 React 基础入门: 一个完整的指南(一)
快速掌握 React 基础入门: 一个完整的指南
|
1月前
|
前端开发 JavaScript 开发者
React中JSX语法入门
React中JSX语法入门
|
7月前
|
前端开发 JavaScript
React基础入门
React基础入门
41 0
|
9月前
|
存储 前端开发 JavaScript
【react从入门到精通】React兄弟组件通信方式详解(有示例)
在上一篇文章《[React父子组件通信方式详解]》中我们学习到了React父子组件通信的4中方式。本文中我们将详细了解react兄弟组件通信方式。
201 0
|
10月前
|
前端开发
前端学习笔记202305学习笔记第二十九天-React keep alive原理之2
前端学习笔记202305学习笔记第二十九天-React keep alive原理之2
45 0
|
10月前
|
前端开发
前端学习笔记202306学习笔记第四十八天-react-admin marmelab之8
前端学习笔记202306学习笔记第四十八天-react-admin marmelab之7
31 0