React 快速入门:掌握前端开发的核心技能

React 快速入门:掌握前端开发的核心技能

一、React 简介

React 的雏形在 Facebook 内部首次出现。由于当时 Facebook 的前端代码越来越复杂,开发团队感受到了传统的 MVC(Model-View-Controller)框架的局限性,开始探索一种更加灵活和高效的前端开发方式。所以 React 就出现了。

1.1 React 的历史

  • 2010 年 Facebook 在其 php 生态中引入了 xhp 框架,首次引入了组合式的思想,启发了后来的 React 的设计。
  • 2011 年 Jordan Walke 创造了 FaxJs,也就是后来的 React 原型。
  • 2012 年在 Facebook 收购 Instagram 后,该 Faxus 项目在内部得到使用。Jordan Walke 基于 FaxJs 的经验,创造了 React。
  • 2013 年 React 正式开源,在 2013 年 Jsconf 上 Jordan Walke 介绍了这款全新的框架。
  • 2014 年------今天生态大爆发,各种围绕 React 的新工具/新框架开始涌现。
  • 2015 年 Jordan 开始捣鼓 React Native 并发布。然后是 Dan 和 Andrew 发明 Redux。
  • 2016 年,React 成为主流。
  • 2017 年,尝试解决性能问题,开始了数年的重构,引入 Fiber 架构。
  • 2019 年,Sebastian 终于设计出了替代 Class 组件副作用的函数式解决方案 - Hooks。完美解决了副作用和业务逻辑复用的问题。
  • 2022 年,v18concurrent 特性上线。
  • 2023 年 React 新文档发布。
  • 2024 年1月29日,React 15.4.0正式版发布,标志着React进入了一个新的发展阶段,带来了一系列新特性和改进。这个版本不仅展示了React在性能优化方面的新进展,也体现了组件化的进一步深化。

1.2 React 的概念

React 是一个由 Facbook 开发的 JavaScript 库,用于构建用户界面。它以可重用的组件为基础,使得开发复杂的用户界面变得更加容易和高效。再 React 中, 组件是用户界面的基本构建块,它们可以接收数据、响应用户交互,以及根据数据的改变而更新。

1.3 React 的特点

  1. 组件化开发:将用户界面拆分为独立的组件,每个组件可以独立开发和更新。
  2. 高效 :React 使用虚拟 DOM 来优化 DOM操作,从而提高应用程序的性能。
  3. 灵活:React 支持单向数据流和组件嵌套,可以方便地构建复杂地应用程序。
  4. 易于维护:React 的代码分离和模块化使得应用程序易于维护。
  5. 支持多种开发方式 :React 支持函数式编程、类式编程和基于魂灵(Hooks)的编程方式。
  6. 社区活跃:React 拥有庞大的开发者社区,并持续推出新特性和更新。

1.4 React 的官网地址

React 官方地址:https://react.docschina.org/

react 中文官网地址:https://react.nodejs.cn/

二、开发环境搭建

在开始使用 React 之前,我们需要设置开发环境。首先,确保你已经安装了 Node.jsnpm。然后,使用以下命令创建一个新的 React 应用:

bash 复制代码
# 创建一个名为 my-app 的 react 应用
npx create-react-app my-app

# 切换到 my-app 目录下
cd my-app

# 启动当前项目
npm start

这将创建一个名为 my-app 的新目录,并启动一个开发服务器,你可以在浏览器中访问http://localhost:3000 来查看你的应用。

三、React 基础

3.1 JSX

JSX 是一种 JavaScript 的语言扩展,它允许你在 JavaScript 中编写类似 HTML 的代码。例如:

jsx 复制代码
const element = <h1>Hello, World!</h1>;

3.2 组件

React 应用由多个组件组成,每个组件都有自己的状态和逻辑。组件可以小到一个按钮,也可以大到整个页面。组件可以是函数或类:

jsx 复制代码
function Welcome(props){
  return <h1>Hello, {props.name}</h1>;
}

至此,你已经声明了Welcome,现在把它嵌套到另一个组件中:

jsx 复制代码
export default function MyApp() {
  return (
    <div>
      <h1>Welcome to my app</h1>
      <Welcome />
    </div>
  );
}

注意:React 组件必须以大写字母开头,而 HTML 标签则必须是小写字母。

3.3 Props

Props 是组件的输入,它们是只读的。你可以将 props 传递给子组件:

jsx 复制代码
function Welcome(props){
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;

3.4 State

通常你会希望你的组件"看记住"一些信息并展示出来,比如一个按钮被点击的次数。要做到这一点,你需要在你的组件中添加 State
State 是组件的私有数据,它可以改变。使用 useState Hook 来在函数组件中添加状态:

jsx 复制代码
// 引入 useState
import React, { useState } from 'react';

function Counter() {
  // 声明一个 state 变量
  const [count, setCount] = useState(0);

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

你将从 useState 中获得两样东西:当前的 state (count),以及用于更新它的函数(setCount)。你可以给它们起任何名字,但按照惯例会像[something, setSomething] 这样给为它们命名。

第一次显示按钮时,count 的值为 0,因为你把 0 传给了 useState() 。当你想改变 state 时,调用 setCount() 并将新的值传递给它。点击该按钮计数器将递增。

如果你多次渲染同一个组件,每个组件都会拥有自己的 state。

jsx 复制代码
import { useState } from 'react';

export default function MyApp() {
  return (
    <div>
      <h1>Counters that update separately</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

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

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} times
    </button>
  );
}

3.5 props 和 state 的区别

关系

  • propsstate 都是组件的状态,但它们有不同的作用域和用途。
  • 当子组件需要传递数据给父组件时,可以使用 props
  • 当组件需要跟组内部状态并进行相应更新时,可以使用 state

区别

  • props只读的 ,父组件传递给子组件,不能改变。而 state可写的 ,子组件可以根据用户交互或其他条件更新 state
  • props 是由父组件提供,而 state 可以由组件自己管理。
  • props 是为了传递数据给子组件,state 则是为了跟踪组件内部状态。

3.6 Hook

use 开头的函数被称为 HookuseState 是 React 提供的一个内置 Hook。

Hook 比普通函数更为严格。你只能在你的组件(或其他 Hook )的 顶层 调用Hook。如果你想在一个条件或循环中使用 useState ,请提取一个新的组件并在组件内部使用它。

常用的 Hook

  • useState:用于在函数组件中添加状态(state)管理。
  • useEffect:用于在函数组件中执行副作用操作,比如订阅数据、设置定时器、手动操作 DOM 等。
  • useRef:用于函数组件中创建可变的引用。
  • useContext:用于在函数组件中使用 Context。

四、React 生命周期

React 组件有多个生命周期方法,它们在组件的不同阶段被调用。常用的生命周期方法包括:

  • componentDidMount: 组件挂载后调用
  • componentDidUpdate: 组件更新后调用
  • componentWillUnMount: 组件卸载前调用

五、添加样式、显示数据

在 React 中, 你可以使用 className 来指定一个 CSS 的 class。它与 HTML 的 class 属性的工作方式相同:

jsx 复制代码
import * as React from 'react';
import './index.css';

const user = {
  name: '张三',
  imageUrl: '/favicon.png',
  imageSize: 90,
};


const HelloWorld = () => {
  function Profile() {
    return (
      <>
        <h1>{user.name}</h1>
        <img
          className="acatar"
          src={user.imageUrl}
          alt={`Photo of ${user.name}`}
          style={{
            width: user.imageSize,
            height: user.imageSize,
          }}
        />
      </>
    );
  }
  return (
    <>
      <h1>Welcome to my app</h1>
      <Profile />
    </>
  );
};

export default HelloWorld;

然后,你可以在一个单独的 CSS 文件中为它编写 CSS 规则:

jsx 复制代码
/* In your CSS */
.avatar {
  border-radius: 50%;
}

React 并没有规定你如何添加 CSS 文件。最简单的方式是使用 HTML 的 <link> 标签。

JSX 会让你把标签放到 JavaScript 中。而大括号会让你"回到"JavaScript 中,这样你就可以从你的代码中嵌入一些变量并展示给用户。user.name 会显示 张三,你还可以将 JSX 属性"转义到 JavaScript",但你必须使用大括号 而非 引号。className="avatar" 是将"avatar" 字符串传递给 className,作为 CSS 的 class。但 src={user.imageUrl} 会读取 JavaScript 的 user.imageUrl 变量,然后将该值作为 src 属性传递。

在上面示例中,style={``{}} 并不是一个特殊的语法,而是 style={ } JSX 大括号内的一个普通 {} 对象。当你的样式依赖于 JavaScript 变量时,你可以使用 style 属性。

六、条件渲染

React 没有特殊的语法来编写条件语句,因此你使用的就是普通的 JavaScript 代码。例如使用if 语句根据条件引入 JSX:

jsx 复制代码
let content;
if (isLoggedIn) {
  content = <AdminPanel />;
} else {
  content = <LoginForm />;
}
return (
  <div>
    {content}
  </div>
);

如果你喜欢更为紧凑的代码,可以使用 condition ? value1 : value2 运算发。与 if 不同的是,它工作与 JSX 内部:

jsx 复制代码
<div>
  {isLoggedIn ? (
    <AdminPanel />
  ) : (
    <LoginForm />
  )}
</div>

当你不需要 else 分支时,你还可以使用 逻辑&& 语法:

jsx 复制代码
<div>
  {isLoggedIn && <AdminPanel />}
</div>

七、渲染列表

你将依赖 JavaScript 的特性,例如 for 循环和 array 的 map() 函数来渲染组件列表。

假设你有一个产品数组:

jsx 复制代码
const products = [
  { title: 'Cabbage', id: 1 },
  { title: 'Garlic', id: 2 },
  { title: 'Apple', id: 3 },
];

在你的组件中,使用 map() 函数将这个数组转换为 <li> 标签构成的列表:

jsx 复制代码
const listItems = products.map(product =>
  <li key={product.id}>
    {product.title}
  </li>
);

return (
  <ul>{listItems}</ul>
);

注意,<li> 有一个 key 属性。对于列表中的每一个元素,你都应该传递一个字符串或者数字给 key,用于在其他兄弟节点中唯一标识该元素。通常 key 来自你的数据,比如数据库中的 ID。如果你在后续插入、删除或重新排序这些项目, React 将依靠你提供的 key 来思考发生了什么。

八、响应事件

你可以通过在组件中声明 **事件处理函数 ** 来响应事件:

jsx 复制代码
function MyButton() {
  function handleClick() {
    alert('You clicked me!');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

注意,onClick={handleClick} 的结尾没有小括号!不要 **调用 **事件处理函数:你只需 把函数传递给事件 即可。当用户点击按钮时 React 会调用你传递的事件处理函数。

九、组件间共享数据

在前面的示例中,每个 MyButton 都有自己独立的 count ,当每个按钮被点击时,只有被点击按钮的count 才会发生改变:

然而,你经常需要组件 共享数据并一起更新

为了使得 MyButton 组件显示相同的 count 并一起更新,你需要将各个按钮的 state "向上"移动到最接近包含所有按钮的组件之中。

在这个示例中,它是 MyApp

此刻,当你点击任何一个按钮时,MyApp 中的 count 都将改变,同时会改变 MyButton 中的两个count。

首先,将 MyButtonstate 上移到 MyApp 中:

jsx 复制代码
export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Counters that update separately</h1>
      <MyButton />
      <MyButton />
    </div>
  );
}

function MyButton() {
  // ... we're moving code from here ...
}

接着,将 MyApp 中的点击事件处理函数以及** state 一同向下传递到** 每个 MyButton 中。你可以使用 JSX 的大括号向 MyButton 传递信息。就像之前向 <img> 等内置标签所做的那样:

jsx 复制代码
export default function MyApp() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <div>
      <h1>Counters that update together</h1>
      <MyButton count={count} onClick={handleClick} />
      <MyButton count={count} onClick={handleClick} />
    </div>
  );
}

使用这种方式传递的信息被称作 prop。此时 MyApp 组件包含了 count state 以及 handleClick 事件处理函数,并将它们作为 **prop 传递给 **了每个按钮。

最后,改变 MyButton 以 **读取 **从父组件传递来的 prop:

jsx 复制代码
function MyButton({ count, onClick }) {
  return (
    <button onClick={onClick}>
      Clicked {count} times
    </button>
  );
}

当你点击按钮时,onClick 处理程序会启动。每个按钮的 onClick prop 会被设置为 MyApp 内的 handleClick 函数,所以函数内的代码会被执行。该代码会调用 setCount(count + 1),使得 state 变量 count 递增。新的 count 值会被作为 prop 传递给每个按钮,因此它们每次展示的都是最新的值。这种成为"
状态提升"。通过向上移动 state,我们实现了在组件间共享它。

相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
光头程序员7 小时前
grid 布局react组件可以循数据自定义渲染某个数据 ,或插入某些数据在某个索引下
javascript·react.js·ecmascript
limit for me7 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者7 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架