React vs Vue:五年全栈老兵的真实体验
从真实项目说起
当时我们面临的是一个实时交易监控系统,需要处理高频数据更新和复杂的交互状态。团队里有三个前端,两个是React背景,一个是Vue背景。我们做了个大胆的决定:用两个星期分别用React和Vue实现同一个核心模块——实时持仓看板。
代码对比:状态管理
React版本(当时用的是Class组件):
class PositionMonitor extends Component {
constructor(props) {
super(props);
this.state = {
positions: [],
sortField: 'profit',
filter: {}
};
this.socket = null;
}
componentDidMount() {
this.socket = new WebSocket(API_URL);
this.socket.onmessage = (event) => {
const data = JSON.parse(event.data);
this.setState(prevState => ({
positions: this.mergePositions(prevState.positions, data)
}));
};
}
mergePositions = (existing, updates) => {
// 复杂的实时数据合并逻辑
return existing.map(pos => {
const update = updates.find(u => u.id === pos.id);
return update ? { ...pos, ...update } : pos;
});
}
handleSort = (field) => {
this.setState({ sortField: field });
}
render() {
const sorted = this.sortPositions(this.state.positions);
return (
<div>
<SortControls onSort={this.handleSort} />
<PositionList positions={sorted} />
</div>
);
}
}
Vue版本:
<template>
<div>
<SortControls @sort-change="handleSort" />
<PositionList :positions="sortedPositions" />
</div>
</template>
<script>
export default {
data() {
return {
positions: [],
sortField: 'profit',
filter: {}
}
},
computed: {
sortedPositions() {
return this.positions.sort((a, b) =>
a[this.sortField] - b[this.sortField]
);
}
},
mounted() {
this.socket = new WebSocket(API_URL);
this.socket.onmessage = (event) => {
const data = JSON.parse(event.data);
this.positions = this.mergePositions(this.positions, data);
};
},
methods: {
handleSort(field) {
this.sortField = field;
},
mergePositions(existing, updates) {
// 同样的合并逻辑
return existing.map(pos => {
const update = updates.find(u => u.id === pos.id);
return update ? { ...pos, ...update } : pos;
});
}
}
}
</script>
两周后的代码评审会上,我们发现了一些有趣的现象:
技术决策的思考过程
1. 学习曲线:Vue确实更友好
团队里那个Vue背景的同事两天就上手了React,但React背景的同事看Vue的模板语法却有点懵。Vue的单文件组件把HTML、CSS、JS放在一起,更符合传统Web开发者的思维习惯。
但这里有个陷阱:简单的项目Vue上手快,但复杂项目里React的显式数据流反而更容易调试。就像我们后来遇到的一个bug,Vue的响应式系统在深层对象更新时行为不太直观,而React的setState虽然啰嗦,但行为可预测。
2. 性能:其实差别没有想象中大
我们做了性能测试,在1000行数据的表格渲染上:
- React: 初次渲染 120ms,更新 45ms
- Vue: 初次渲染 110ms,更新 38ms
差别微乎其微。真正的性能瓶颈在于我们自己的代码,比如那个mergePositions函数,优化后性能提升了3倍。
3. 生态系统:React赢了规模,Vue赢了体验
React的生态确实更丰富,但这也意味着选择成本更高。我们需要在几十个状态管理库中选择(最后选了Zustand,因为Redux太重了)。Vue的官方生态更一体化,Vuex、Vue Router都是官方维护,决策成本低。
2023年的新认知
五年过去了,两个框架都发生了很大变化:
Hooks改变了React
// 现代React代码
function PositionMonitor() {
const [positions, setPositions] = useState([]);
const [sortField, setSortField] = useState('profit');
const sortedPositions = useMemo(() => {
return [...positions].sort((a, b) => a[sortField] - b[sortField]);
}, [positions, sortField]);
useEffect(() => {
const socket = new WebSocket(API_URL);
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
setPositions(prev => mergePositions(prev, data));
};
return () => socket.close();
}, []);
return (
<div>
<SortControls onSort={setSortField} />
<PositionList positions={sortedPositions} />
</div>
);
}
Hooks让React代码更简洁,但需要理解闭包陷阱和依赖数组。我们团队花了两个月才完全适应,期间踩了不少坑。
Vue 3的Composition API
<template>
<div>
<SortControls @sort-change="setSortField" />
<PositionList :positions="sortedPositions" />
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
const positions = ref([]);
const sortField = ref('profit');
const sortedPositions = computed(() => {
return positions.value.sort((a, b) => a[sortField.value] - b[sortField.value]);
});
onMounted(() => {
const socket = new WebSocket(API_URL);
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
positions.value = mergePositions(positions.value, data);
};
});
</script>
Vue 3的Composition API让代码组织更灵活,但失去了原来选项式API的清晰结构。我们有些老项目迁移时遇到了类型推断的问题。
真实项目中的痛点对比
状态管理复杂度
React + Zustand:
// store/counter.js
const useCounter = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
// 组件使用
function Counter() {
const { count, increment } = useCounter();
return <button onClick={increment}>{count}</button>;
}
Vue + Pinia:
// stores/counter.js
export const useCounter = defineStore('counter', () => {
const count = ref(0);
function increment() {
count.value++;
}
return { count, increment };
});
// 组件使用
const counter = useCounter();
React的状态管理更自由但需要更多决策,Vue的更标准化但有时不够灵活。
TypeScript支持
React的TS支持确实更好,特别是泛型组件:
interface ListProps<T> {
items: T[];
renderItem: (item: T) => ReactNode;
}
function List<T>({ items, renderItem }: ListProps<T>) {
return <div>{items.map(renderItem)}</div>;
}
Vue的模板内类型检查还在完善中,但Script Setup+TypeScript已经很好用了。
我的选择标准
经过这么多项目,我现在这样选择:
选择React当:
- 团队有React经验
- 项目复杂度高,需要自定义抽象
- 需要服务端渲染(Next.js生态更成熟)
- 团队喜欢函数式编程
选择Vue当:
- 团队前端经验较浅
- 项目需要快速上线
- 需要更好的开发体验(Vue Devtools很棒)
- 项目规模中等,不需要太复杂的抽象
一些反常识的发现
- 文档质量:Vue的文档确实更好,但React的社区解答更丰富
- 招聘难度:React程序员更多,但Vue程序员更稳定(个人观察)
- 长期维护:Vue 2到3的迁移比React 15到16痛苦得多
- 移动端:React Native确实是个优势,但现在Vue也有了不错的移动方案
给团队的技术建议
如果是新项目:考虑团队背景,两个都是好选择。我更倾向于React,因为它的思维模型更通用,学会了React再学Vue很容易,反过来则不然。
如果是老项目重构:用团队熟悉的框架。重写成本远高于框架差异带来的收益。
如果是创业公司:Vue可能更适合,开发速度更快,招初级程序员成本更低。
框架选择就像选结婚对象,没有最好,只有最合适。我们团队现在两个框架都在用,重要的是理解它们的设计哲学,而不是死磕技术细节。
最后分享一个真实数据:我们最近一年维护的6个项目中,4个用React,2个用Vue,项目成功率都是100%。框架本身不决定项目成败,团队的技术能力和工程实践才是关键。
更多推荐


所有评论(0)