React基础知识(补充中)
一、React 基础概念
1.1 什么是 React
React 是由 Facebook(现 Meta)开发并开源的 JavaScript 库,专门用于构建用户界面(UI)。在传统的 Web 开发中,当页面内容发生变化时,往往需要重新渲染整个页面,这会造成性能浪费
。而 React 打破了这种模式,它采用组件化开发思想,将复杂的 UI 拆解成一个个独立、可复用的组件
。这些组件就像是搭建房屋的积木,开发者可以根据需求自由组合,大大提升了代码的可维护性与扩展性。
React 专注于 UI 层的构建
,不负责处理应用的整体状态和复杂逻辑
(当然,通过搭配其他库可以实现)。它通过独特的虚拟 DOM 机制和高效的渲染算法,能够快速、精准地更新页面内容,为用户带来流畅的交互体验。例如,在一个电商应用中,商品列表、购物车、用户信息展示等部分都可以分别封装成组件,独立开发和维护。
1.2 React 的核心特性
组件化开发:组件
是 React 的核心,它将 UI 进行模块化拆分,每个组件都有自己的逻辑和视图。比如一个博客应用,文章列表、文章详情、评论区都可以是独立的组件。
组件可以嵌套使用
,父组件可以向子组件传递数据(通过 props),子组件也可以触发父组件的函数,实现组件间的通信与交互。组件化开发使得代码结构清晰,功能复用性高,当某个组件需要修改时,不会轻易影响到其他组件,降低了开发和维护的成本。
虚拟 DOM:
真实的 DOM 操作是比较消耗性能
的,因为每次对 DOM 的修改都会引发浏览器的重排与重绘
。React 为了解决这个问题,引入了虚拟 DOM
。
当组件的状态或 props 发生变化时,React 会首先在内存中创建一个虚拟的 DOM 树,这个虚拟 DOM 树就像是真实 DOM 的 “影子”。React 会计算出新的虚拟 DOM 树和旧的虚拟 DOM 树之间的差异(这个过程称为 “diffing 算法”),然后只将差异部分应用到真实 DOM 上
,从而最小化对真实 DOM 的操作,大幅提升渲染性能。例如,当一个列表新增了一项数据,React 不会重新渲染整个列表,而是只更新新增的那一项对应的 DOM 节点。
单向数据流:
在 React 中,数据的流动方向是单向的
,从父组件流向子组件。父组件通过 props 将数据传递给子组件,子组件只能接收和使用这些数据
,不能直接修改
它们。
如果子组件需要修改数据
,通常需要通过回调函数
通知父组件,由父组件来更新数据,然后再重新传递给子组件
。这种单向数据流的方式让数据的流向清晰可控,便于开发者追踪数据变化和调试代码,避免了数据混乱导致的难以排查的问题。
二、环境搭建与项目创建
在开始 React 开发之前,搭建好开发环境并创建项目是首要任务。
2.1 安装 Node.js
React 项目依赖 Node.js 运行,Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,它让 JavaScript 可以在服务器端运行,同时也提供了丰富的包管理功能
。
你可以访问 Node.js 官方网站(https://nodejs.org/),根据自己的操作系统(Windows、Mac 或 Linux)下载对应的安装包。下载完成后,双击安装包,按照安装向导的提示进行操作,过程中可以选择安装路径等设置。
安装完成后,打开命令行工具(Windows 系统可以使用 CMD 或 PowerShell,Mac 和 Linux 系统使用终端),分别输入node -v
和npm -v
命令。如果命令行返回了 Node.js 和 npm 的版本号,说明安装成功。其中,node -v用于查看 Node.js 的版本,npm -v用于查看 npm(Node 包管理器)的版本,npm 是 Node.js 默认的包管理工具,用于安装、管理项目所需的各种依赖包。
2.2 创建 React 项目
创建 React 项目最常用的工具是create-react-app
,它是 Facebook 官方提供的脚手架工具,能够快速生成一个配置好的 React 项目模板
,省去了手动配置各种构建工具(如 Webpack、Babel 等)的繁琐过程。
打开命令行工具,进入你想要创建项目的目录(例如,你想在桌面上创建项目,可以先在命令行中输入cd Desktop进入桌面目录),然后执行以下命令:
npx create-react-app my-react-app
这里的npx是 npm 5.2.0 引入的一个命令,它可以自动查找当前依赖包中的可执行文件,如果找不到就会去下载
。create-react-app是创建
React 项目的命令,my-react-app
是项目的名称
,你可以根据自己的需求修改为其他名称。
执行命令后,create-react-app会自动下载项目所需的各种依赖包,并生成项目的基本结构,这个过程可能需要一些时间,具体取决于你的网络速度。安装完成后,进入项目目录:
cd my-react-app
接着启动项目:
npm start
此时,命令行工具
会启动一个本地开发服务器,浏览器会自动打开http://localhost:3000
页面,你将看到 React 项目的默认页面,页面上显示着 “Welcome to React” 等字样。如果浏览器没有自动打开,你也可以手动在浏览器地址栏中输入http://localhost:3000访问项目。
三、React 组件
3.1 函数式组件
函数式组件
是 React 中最简洁、最常用的组件形式,它本质上就是一个普通的 JavaScript 函数。这个函数接收一个props(属性)对象作为参数
,props用于接收父组件传递过来的数据,然后函数返回一个 React 元素(通常是使用 JSX 语法编写的)
,这个元素定义了组件的视图结构。
import React from'react';
// 定义一个简单的函数式组件HelloWorld
const HelloWorld = (props) => {// 从props中获取name属性return <div>Hello, {props.name}!</div>;
};export default HelloWorld;
在上述代码中,HelloWorld
函数就是一个函数式组件。当父组件使用<HelloWorld name="Alice" />
这种方式调用该组件时,props对象就会包含{ name: "Alice" }
,然后在组件的返回值中,通过{props.name}将传递过来的名字显示在页面上。
函数式组件还有一个特点,就是它是无状态
的(在不使用钩子的情况下),即它不包含自身的状态数据
。不过,自从 React 引入了钩子(如useState)后,函数式组件也可以拥有状态
,从而具备了更强大的功能。
3.2 组件通信
1. 父组件向子组件通信
这是最常见的通信方式,通过 props
来实现。父组件可以将数据、函数等作为 props 传递给子组件,子组件接收并使用这些 props。
// 子组件
const ChildComponent = (props) => {return (<div><p>来自父组件的消息: {props.message}</p></div>);
};// 父组件
const ParentComponent = () => {const message = "Hello from parent";return (<div><ChildComponent message={message} /></div>);
};export default ParentComponent;
在上述代码中,ParentComponen
t 将 message 作为 props 传递给 ChildComponent,ChildComponent 则通过 props.message 来获取该值。
2. 子组件向父组件通信
子组件向父组件通信通常是通过父组件传递一个回调函数给子组件,子组件在需要时调用这个回调函数并传递数据。
// 子组件
const ChildComponent = (props) => {const handleClick = () => {props.onClick("Hello from child");};return (<button onClick={handleClick}>发送消息给父组件</button>);
};// 父组件
const ParentComponent = () => {const handleChildMessage = (message) => {console.log("收到子组件的消息:", message);};return (<div><ChildComponent onClick={handleChildMessage} /></div>);
};export default ParentComponent;
这里,ParentComponent 传递了 handleChildMessage 函数给 ChildComponent,ChildComponent 在按钮点击时调用该函数并传递消息。
3. 兄弟组件通信
兄弟组件之间的通信可以借助共同的父组件
来实现。一个兄弟组件通过触发父组件的回调函数传递数据给父组件,父组件再将数据传递给另一个兄弟组件。
// 第一个子组件
const FirstChild = (props) => {const handleClick = () => {props.onSendMessage("Message from FirstChild");};return (<button onClick={handleClick}>发送消息给另一个兄弟组件</button>);
};// 第二个子组件
const SecondChild = (props) => {return (<div><p>收到的消息: {props.message}</p></div>);
};// 父组件
const ParentComponent = () => {const [message, setMessage] = React.useState("");const handleSendMessage = (msg) => {setMessage(msg);};return (<div><FirstChild onSendMessage={handleSendMessage} /><SecondChild message={message} /></div>);
};export default ParentComponent;
在这个例子中,FirstChild 点击按钮触发 ParentComponent 的 handleSendMessage 函数,ParentComponent 更新 message 状态并将其传递给 SecondChild。
4. 跨级组件通信
当组件嵌套层级较深时,使用 props 逐层传递数据会变得繁琐,此时可以使用 Context 来实现跨级组件通信。
// 创建 Context
const MyContext = React.createContext();// 深层子组件
const DeepChild = () => {const contextValue = React.useContext(MyContext);return (<div><p>从顶层组件接收到的值: {contextValue}</p></div>);
};// 中间组件
const MiddleComponent = () => {return (<div><DeepChild /></div>);
};// 顶层组件
const TopComponent = () => {const value = "Data from top component";return (<MyContext.Provider value={value}><MiddleComponent /></MyContext.Provider>);
};export default TopComponent;
Context 提供了一个 Provider
组件用于提供数据,以及一个 useContext 钩子用于在子组件中获取数据,这样就可以跨越中间层级直接传递数据。
5. 全局状态管理库(如 Redux、MobX)
对于大型应用,使用全局状态管理库可以更方便地管理组件间的通信。以 Redux 为例:
import { createStore } from'redux';
import { Provider, useSelector, useDispatch } from'react-redux';// 定义 reducer
const counterReducer = (state = { count: 0 }, action) => {switch (action.type) {case 'INCREMENT':return { count: state.count + 1 };case 'DECREMENT':return { count: state.count - 1 };default:return state;}
};// 创建 store
const store = createStore(counterReducer);// 增加计数的组件
const IncrementButton = () => {const dispatch = useDispatch();const handleClick = () => {dispatch({ type: 'INCREMENT' });};return (<button onClick={handleClick}>增加计数</button>);
};// 显示计数的组件
const CounterDisplay = () => {const count = useSelector(state => state.count);return (<div><p>当前计数: {count}</p></div>);
};// 根组件
const App = () => {return (<Provider store={store}><IncrementButton /><CounterDisplay /></Provider>);
};export default App;
Redux 通过 store 来存储全局状态,组件可以通过 useSelector 来获取状态,通过 useDispatch 来触发 action 更新状态。这样不同组件可以方便地共享和修改全局状态。
vue和react的比较
1. 语法与学习门槛
- React
React 运用JSX
语法,这是 JavaScript 的拓展,允许在 JavaScript 里编写类似 HTML 的代码。这要求开发者熟悉JavaScript 的高级特性
,像函数式编程、高阶组件等。例如创建一个简单的组件:
import React from'react';const MyComponent = () => {return <div>Hello from React!</div>;
};export default MyComponent;
对于初学者而言,JSX 的语法和 React 的函数式编程思想可能有一定学习难度。
- Vue 3
Vue 3 采用模板语法
,与传统 HTML 相似,同时结合了 JavaScript 表达式。它也支持使用 Composition API 以更灵活地组织逻辑。下面是一个简单组件示例:
<template><div>Hello from Vue 3!</div>
</template><script setup>
// Composition API 相关代码可写在此处
</script>
其模板语法直观易懂,降低了新手的学习门槛,即便没有深厚 JavaScript 基础的开发者也能快速上手。
2. 组件化开发方式
- React
强调组件的纯粹性和不可变数据
。组件通常是纯函数或类
,数据单向流动
,推荐使用不可变数据确保数据的可预测性
。例如更新状态时,需返回新的状态对象:
import React, { useState } from'react';const Counter = () => {const [count, setCount] = useState(0);const increment = () => {setCount(prevCount => prevCount + 1);};return (<div><p>Count: {count}</p><button onClick={increment}>Increment</button></div>);
};export default Counter;
组件之间的通信主要通过 props 和回调函数
实现,对于复杂场景可能需要借助状态管理库
。
- Vue 3
支持多种组件开发风格,既可以使用传统的选项式 API,也能采用 Composition API 更灵活地组织逻辑
。数据响应式系统使得直接修改数据时,相关的 DOM 会自动更新
。示例如下:
<template><div><p>Count: {{ count }}</p><button @click="increment">Increment</button></div>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
const increment = () => {count.value++;
};
</script>
组件通信方式多样,除了 props 和事件
,还能使用 provide/inject
、event bus
等,对于复杂应用,也有 Vuex 等状态管理库。
3. 状态管理
- React
本身没有内置的状态管理方案,简单状态可使用useState
和useReducer
钩子处理,复杂应用常依赖第三方库,如 Redux 或 MobX
。以 Redux 为例,遵循单向数据流原则,通过 action、reducer 和 store 管理应用状态
。 - Vue 3
内置响应式系统
和Vuex 作为状态管理库
。Vuex 与 Vue 的响应式系统深度集成,使用起来更简洁。同时,Vue 3 的 Composition API 让状态管理更加灵活,可自定义响应式逻辑。
4. 虚拟 DOM 实现
- React
虚拟 DOM 是核心特性,通过 diff 算法对比新旧虚拟 DOM 树的差异,仅更新需要变化的真实 DOM 节点。React 的 diff 算法复杂但灵活
,能应对各种复杂的组件嵌套和更新情况。 - Vue 3
虚拟 DOM 实现相对轻量,基于依赖追踪的响应式系统,能精准知晓哪些数据发生变化,仅更新与之绑定的 DOM 节点
。在小规模更新场景下,性能表现更优。
5. 生态系统和社区支持
- React
拥有庞大的生态系统
,有海量的第三方库和工具,适用于各种场景。社区活跃,有众多优秀的开源项目和教程。由于由 Meta 开发维护,在企业级应用开发中广泛应用。 - Vue 3
生态系统也在持续发展
,有许多实用的插件和工具。社区氛围友好,初学者容易获得帮助。因简单易用,在中小型项目中应用广泛。
6. 路由管理
- React
常用React Router
进行路由管理,提供丰富功能和灵活配置选项,支持动态路由、嵌套路由等。 - Vue 3
有官方的Vue Router
,与 Vue 3 框架紧密集成,使用便捷,同样支持多种路由模式和功能。
7. 渲染机制
https://www.doubao.com/thread/w51e915a25b1f9662
- React
采用基于事件驱动的渲染机制,当状态或 props 改变时,会触发组件的重新渲染。尽管有 React.memo 等优化手段,但有时仍会出现不必要的渲染
。 - Vue 3
利用细粒度的响应式系统,能精确追踪数据变化,只更新依赖该数据的 DOM 部分,减少不必要的渲染,在某些场景下性能更优
。