React 与 Vue 终极指南:从核心原理到高级实战全解析
React 和 Vue 的核心设计理念
首先我们要知道,react,和vue的设计理念,区分框架的基本
react的核心思想是“单向数据流”,
vue的核心是双向绑定
我们了解单向和双向,非常容易
react单向数据量,从字面上来讲,指的是,数据是单向,且不可回,就像水流一样,奔流到海不复回,不可能再让水倒流回来吧。
在react代码中,大到组件传参,小到变量声明,都遵守这单向
javascript 当中 定义变量 有 let const var
react hooks 创建变量 ,是由 const [data,setData]=useState() hooks来声明
data 是我们创建的变量, setData 是我们修改变量的方法函数,这里注意 setData就是一个函数,react 要求状态更新必须通过 setData 完成,直接修改 data(如 data.push(...))不会触发渲染 这样就好比如 我想直接 通过 data=‘123’ 这种 调用修改的方式 是不存在的.不同于 vue 中 可以this.data=123,可以直接用ref reactive声明的数据 ,两者的框架逻辑,底层也是不一致的
其实说到这里,讲他们的设计理念,也牵扯到 渲染原理,触发机制,框架底层监听,就好比与你修改了变量,那视图更不更新?
vue通过 this.data=**** 因为是双向绑定 ,你变化了就更新试图,这是vue的设计模式mvvm
react 就不会 ,react 必须要通过 hooks setData的形式 才可以 这也是react框架要求的
我们再说到到组件层次 ,
- React:
- 子组件绝对不能直接修改父组件传递的props,必须通过回调函数(如父组件传递的setState函数)来通知父组件更新状态。
- 这种设计强制单向数据流,确保数据变化可预测,避免副作用。
- Vue
- 双向同步能力:通过
v-model或.sync修饰符实现父组件与子组件的双向绑定。子组件可通过$emit触发事件通知父组件更新数据,同时父组件数据变化自动同步到子组件。 - 反模式警告:虽然技术上子组件可直接修改props(如Vue 2的
this.prop = newValue),但Vue官方强烈反对,因其破坏单向数据流。Vue 3通过响应式系统检测props修改并发出警告,推荐使用emit或computed属性
- 双向同步能力:通过
框架的应用不仅仅是框架的特点等等,同是跟项目类型,开发效率,开发周期,后期优化等
这篇文章有很深的见解从0到1:一名前端程序员的项目沉思录-CSDN博客,
虚拟dom
react,vue 都是 通过真实dom构建虚拟dom,页面修改变量,函数,不会去直接去修改真实dom,而是去改变虚拟dom,然后虚拟dom 和真实dom 之间通过 diff 算法,来对比差异. 这就像 去写协同编辑,在线编辑,对比差异 ,差异算法,
- React(Fiber架构 + 单向递归)
- 分层比较:仅对比同层级节点,不跨层级移动节点(如节点从A层移到B层会销毁重建)。
- Key机制:依赖唯一
key标识列表元素,通过key匹配节点以优化移动、添加或删除操作。无key时按索引顺序比较,可能导致列表头部插入时后续节点全部重建。 - Fiber架构:将Diff过程分解为多个阶段(如协调、提交),支持异步渲染和优先级调度,适合处理复杂UI和频繁更新(如动画、高频交互)。
- Vue(双端比较 + 静态优化)
- 双端指针法:从新旧节点的头尾同时开始比较(头头、尾尾、头尾、尾头),优先复用两端相同的节点,减少中间部分的更新。
- 静态标记(Patch Flags):编译时标记静态节点(如无绑定的纯文本),跳过运行时Diff,减少对比开销。
- 最长递增子序列(LIS):在列表操作中(如移动、插入)通过LIS算法确定最小移动路径,减少DOM操作次数(例如列表反转仅需1次移动)
React Hooks 全面解析
// 基础hooks
import React, { useState, useEffect, useContext } from 'react';
// useState - 状态管理
function Counter() {
const [count, setCount] = useState(0);
const [user, setUser] = useState({ name: '', age: 0 });
// 函数式更新
const increment = () => setCount(prev => prev + 1);
return <button onClick={increment}>{count}</button>;
}
// useEffect - 副作用处理
function DataFetcher({ id }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let isMounted = true;
const fetchData = async () => {
try {
const response = await fetch(`/api/data/${id}`);
const result = await response.json();
if (isMounted) {
setData(result);
setLoading(false);
}
} catch (error) {
if (isMounted) setLoading(false);
}
};
fetchData();
// 清理函数
return () => {
isMounted = false;
// 取消请求或其他清理操作
};
}, [id]); // 依赖数组
return loading ? <div>Loading...</div> : <div>{data}</div>;
}
// useContext - 跨组件数据传递
const ThemeContext = React.createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Click me</button>;
}
高级 hooks
import React, { useReducer, useCallback, useMemo, useRef, useImperativeHandle } from 'react';
// useReducer - 复杂状态逻辑
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return { count: 0 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}
// useCallback - 记忆函数
function Parent() {
const [count, setCount] = useState(0);
// 只有count变化时才会重新创建
const handleClick = useCallback(() => {
console.log('Count:', count);
}, [count]);
return <Child onClick={handleClick} />;
}
// useMemo - 记忆计算结果
function ExpensiveComponent({ list }) {
const sortedList = useMemo(() => {
return list.sort((a, b) => a.value - b.value);
}, [list]); // 只有list变化时重新计算
return <div>{sortedList.map(item => <div key={item.id}>{item.value}</div>)}</div>;
}
// useRef - DOM引用和可变值
function TextInput() {
const inputRef = useRef(null);
const intervalRef = useRef();
useEffect(() => {
// 存储定时器ID
intervalRef.current = setInterval(() => {
// 执行某些操作
}, 1000);
return () => clearInterval(intervalRef.current);
}, []);
const focusInput = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>Focus</button>
</>
);
}
// useImperativeHandle - 暴露子组件方法
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
scrollIntoView: () => {
inputRef.current.scrollIntoView();
}
}));
return <input ref={inputRef} />;
}
FancyInput = React.forwardRef(FancyInput);
React 高级特性
/ 创建Context
const UserContext = React.createContext({
user: null,
login: () => {},
logout: () => {}
});
// Provider组件
function UserProvider({ children }) {
const [user, setUser] = useState(null);
const login = async (credentials) => {
const userData = await loginAPI(credentials);
setUser(userData);
};
const logout = () => {
logoutAPI();
setUser(null);
};
return (
<UserContext.Provider value={{ user, login, logout }}>
{children}
</UserContext.Provider>
);
}
// 消费Context
function UserProfile() {
const { user, logout } = useContext(UserContext);
return (
<div>
<h1>Welcome, {user.name}</h1>
<button onClick={logout}>Logout</button>
</div>
);
}
Refs转发和DOM操作
// Refs转发
const CustomInput = React.forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
// 在父组件中使用
function Parent() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <CustomInput ref={inputRef} />;
}
Vue 3 Composition API
模板语法糖
<template>
<!-- 条件渲染 -->
<div v-if="isVisible">Visible</div>
<div v-else>Not Visible</div>
<!-- 列表渲染 -->
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- 动态绑定 -->
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
<button :disabled="isDisabled">Click</button>
<!-- 事件处理 -->
<button @click="handleClick">Click</button>
<form @submit.prevent="handleSubmit"></form>
<!-- 双向绑定 -->
<input v-model="message">
<input v-model.number="age" type="number">
<!-- 插槽 -->
<BaseLayout>
<template #header>
<h1>Header</h1>
</template>
<p>Main content</p>
</BaseLayout>
</template>
组件通信
<!-- 父组件 -->
<template>
<ChildComponent
:title="pageTitle"
@update-title="pageTitle = $event"
/>
</template>
<!-- 子组件 -->
<script>
export default {
props: {
title: String
},
emits: ['update-title'],
methods: {
updateTitle(newTitle) {
this.$emit('update-title', newTitle);
}
}
};
</script>
<!-- Provide/Inject 跨层级通信 -->
<script>
// 祖先组件
export default {
provide() {
return {
theme: 'dark',
user: reactive({ name: 'John' })
};
}
};
// 后代组件
export default {
inject: ['theme', 'user']
};
</script>
自定义指令
// 全局指令
app.directive('focus', {
mounted(el) {
el.focus();
}
});
// 局部指令
export default {
directives: {
highlight: {
mounted(el, binding) {
el.style.backgroundColor = binding.value || 'yellow';
},
updated(el, binding) {
el.style.backgroundColor = binding.value;
}
}
}
};
// 使用
<div v-highlight="'red'"></div>
|
特性 |
React |
Vue |
|---|---|---|
|
设计理念 |
函数式编程 |
渐进式框架 |
|
学习曲线 |
相对陡峭 |
相对平缓 |
|
模板系统 |
JSX |
模板语法 |
|
状态管理 |
不可变状态 |
可变状态 |
|
样式方案 |
CSS-in-JS/CSS Modules |
Scoped CSS/CSS Modules |
更多推荐

所有评论(0)