说下React[1]和 Vue[2]的区别
![](/files/attmgn/2024/7/admin20240725010153494_0.jpg)
![](/files/attmgn/2024/7/admin20240725010153868_1.jpg)
前言面试时候,有没有面试官问你:“那你说下React 和 Vue 有什么区别?”
该学习了,童鞋!!!
一、编程风格 (Template)
Vue
使用基于 HTML 的模板语法,允许开发者直接在模板中使用指令和插值表达式
<template>
<div>
<p>{{ message }}</p>
<button @click="handleClick">Click me</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello, Vue!'
};
},
methods: {
handleClick() {
alert('Button clicked!');
}
}
};
</script>
<style>
// 样式
</style>
React
使用 JSX 语法,将 HTML 和 JavaScript 结合在一起,需要在代码中编写类似 HTML 的结构。
import React, { useState } from 'react';
function App() {
const [message, setMessage] = useState('Hello, React!');
const handleClick = () => {
alert('Button clicked!');
};
return (
<div>
<p>{message}</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default App;
二、指令功能 (Directives)
1、条件渲染
Vue
v-if
:用于条件性地渲染元素。它基于表达式的值来决定是否显示或隐藏元素。
<div v-if="isShown">这个元素会根据 isShown 的值进行条件渲染</div>
React
在React中,可以使用条件语句(如if
、switch
)或三元表达式来实现条件渲染。
{isShown && <div>这个元素会根据 isShown 的值进行条件渲染</div>}
2、列表渲染
Vue
v-for:用于基于数组或对象的数据来循环渲染元素。它可以遍历数组或对象的每个条目,并为每个条目生成相应的元素。
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
React
使用map
函数来遍历数组或对象,并返回相应的元素。
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
3、属性绑定
Vue
v-bind
(简写为 :
):用于动态地绑定属性或表达式到元素上。它可以将数据绑定到元素的属性、样式或其他特性上。
<img :src="imageSrc" :alt="imageAlt">
React
在React中,可以直接使用JavaScript表达式来动态地设置元素的属性
<img src={imageUrl} alt={imageAlt} />
4、事件处理
Vue
v-on
(简写为 @
):用于监听DOM事件并触发相应的方法。它可以将方法绑定到元素的事件上,如点击、鼠标移入等。
<button v-on:click="handleClick">点击我触发 handleClick 方法</button>
React
在React中,可以直接将事件处理函数指定为元素的属性。使用箭头函数或绑定this
来确保正确的上下文。
<button onClick={handleClick}>点击我触发 handleClick 方法</button>
5、表单双向绑定
Vue
v-model:用于在表单元素和应用程序状态之间创建双向数据绑定。它可以将表单元素的值与Vue实例中的数据进行同步。
<input v-model="message" type="text">
React
在React中,可以通过将表单元素的值与组件的状态(state)进行绑定,使用onchange事件来更新状态。
<input value={message} onChange={(e) => setMessage(e.target.value)}
type="text" />
三、组件风格 (Components)
这里介绍 React16.8 后的 的 函数组件 和 Vue3.0 后的组合式API
React Hook
React Hook 是 React 16.8 版本引入的一项新特性,它能够让函数组件拥有类组件中的状态(state)和生命周期方法(lifecycle methods)等功能。React Hook 包括了多个钩子函数(hook functions),如 useState、useEffect、useContext 等,在函数组件中使用这些钩子函数可以实现一系列常见的功能,如管理组件内部的状态、处理副作用等。React Hook 的出现使得函数组件可以更加灵活地处理复杂的逻辑,同时也提供了一种清晰且可重用的代码结构,使得代码易于维护和扩展。
import React, { useState, useEffect } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Component did mount');
return () => {
console.log('Component will unmount');
};
}, []);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
};
export default Counter;
这个组件使用了useState钩子来保存并更新一个计数器的状态。当用户点击按钮时,计数器会增加,并且在 UI 中显示出来。该 Hook 接受初始状态作为参数,并返回当前状态和一个更新状态的函数。在此示例中,我们使用数组解构将状态值和更新函数分配给count和setCount变量。每次用户单击按钮时,我们用setCount函数更新count的状态。
Vue hook
Vue 3.x 开始引入了 Hooks API,用于在函数式组件中实现状态和生命周期的管理。类似于 React 中的 Hooks,Vue 的 Hooks API 包括 setup() 和一些预置的 hooks 函数,如 ref()、watch()、onMounted() 等等,可以让我们更方便地编写函数式组件,并且具有更好的性能表现。其中,setup() 函数会在组件创建之前被调用,它接收两个参数:props 和 context。在 setup() 函数内部,我们可以使用预置的 hooks 函数来定义响应式数据、监听数据变化、执行副作用等操作,最后返回一个对象,该对象中包含模板中所需要使用的数据和方法。
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
import { ref, onMounted, onUnmounted } from 'vue';
export default {
name: 'Counter',
setup() {
const count = ref(0);
onMounted(() => {
console.log('Component mounted');
});
onUnmounted(() => {
console.log('Component unmounted');
});
const increment = () => {
count.value++;
};
return {
count,
increment
};
}
};
</script>
在这个示例中,我们使用了 Vue 3 的 setup 函数来定义组件的逻辑。通过 ref 函数,我们创建了一个响应式的变量 count,并将其初始值设为 0。然后,我们定义了一个名为 increment 的函数来增加 count 的值。
在模板中,我们显示了当前的 count 值,并在按钮上绑定了 increment 函数。当点击按钮时,count 的值会增加,同时视图也会自动更新以反映新的值。
四、路由风格 (Router)
Vue
采用 Vue-Router (4.X)
npm install vue-router
配置实现(vue 3.0)
router/index.js 创建路由器实例
import { createRouter, createWebHistory } from 'vue-router';
// 创建路由实例
const router = createRouter({
history: createWebHistory(), // 使用hash模式可以用createWebHashHistory
routes: [
{ path: '/', component: () => import('../pages/Home/index.vue') },
{ path: '/home', component: () => import('../pages/Home/index.vue') },
{ path: '/about', component: () => import('../pages/About/index.vue') },
// 更多的路由...
],
});
export default router;
main.js 路由配置
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index';
import './index.css'
const app = createApp(App);
app.use(router);
app.mount('#app');
App.vue 使用路由
<div id="app">
<router-view></router-view>
</div>
跳转实现
声明式
Vue中,使用 <router-link>
组件来创建声明式导航链接,通过 to
属性指定目标路由的路径。
<template>
<div>
<router-link to="/about">Go to About</router-link>
</div>
</template>
编程式
Vue 中,可以通过 vue-route中的useRouter方法,执行函数式导航,使用 router.push方法实现跳转。
tips: vue3.X 中的useRouter 相当于 vue2.X 的 this.$router
<template>
<div>
<button @click="jump('/home')">home</button>
<button @click="jump('/about')">About</button>
</div>
</template>
<script setup>
import { useRouter } from 'vue-router';
const router = useRouter()
const jump=(url = '')=>{
router.push(url)
}
</script>
React
采用 React-Router (6.X)
npm install react-router-dom
配置实现(react 18.2)
rouetr/index.js 创建路由器实例和路由配置
import React from 'react'
import { Routes, Route} from 'react-router-dom'
import Home from '../pages/home/index.jsx'
const Router = () => {
return (
<Routes>
<Route path="/home" element={<Home />}></Route>
</Routes>
)
}
export default Router
index.js 使用路由
import React from 'react';
import ReactDOM from 'react-dom/client';
import Router from './router/index';
import { BrowserRouter} from 'react-router-dom'
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<Router />
</BrowserRouter>
</React.StrictMode>
);
跳转实现
声明式
React中,使用 <Link>
组件来创建声明式导航链接,通过 to
属性指定目标路由的路径
import { Link } from 'react-router-dom';
const Navigation = () => {
return (
<div>
<Link to="/about">Go to About</Link>
</div>
);
};
编程式
React 中,可以通过 useHistory
钩子来获取路由历史对象,并用 history.push
方法进行函数式导航。
import { useHistory } from 'react-router-dom';
const Navigation = () => {
const history = useHistory();
const navigateToAbout = () => {
history.push('/about');
};
return (
<div>
<button onClick={navigateToAbout}>Go to About</button>
</div>
);
};
五、状态管理 (Store)
这里区别在于,Vue 主推 Vuex[3] 和 Pinia[4], React 偏向使用 Redux 和 Mobx。
Vuex
和 Pinia
是专门为 Vue.js
设计的状态管理库,因此它们的语法和API都非常类似。而 Redux
和 Mobx
可以在任何 JavaScript
应用程序中使用,因此他们的语法和API和特定框架没有关系。
Pinia (Vue)
依赖安装
npm install pinia
main.js 创建引入Pinia实例
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
import router from './router/index';
import './index.css'
const app = createApp(App);
const pinia = createPinia();
app.use(router);
app.use(pinia);
app.mount('#app');
store/counter.js 创建状态存储模块
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
actions: {
increment() {
this.count++
},
},
})
Home/index.vue 组件中使用
<template>
<!-- 直接从 store 中访问 state -->
<div>{{ counter.count }}</div>
<button @click="add">点我</button>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
const add = () => {
counter.increment()
}
</script>
Mobx (React)
依赖安装
npm install mobx mobx-react --save
store/counter.js 配置数据存储模块
import { makeAutoObservable } from 'mobx';
class CounterStore {
constructor() {
makeAutoObservable(this);
}
count = 0;
increment = () => {
this.count++;
}
decrement = () => {
this.count--;
}
}
const counterStore = new CounterStore();
export default counterStore;
Home/index.jsx 组件中使用
import React from 'react';
import { observer } from 'mobx-react';
import counterStore from '@/store/counter';
const Counter = observer(() => {
return (
<div>
<h2>Count: {counterStore.count}</h2>
<button onClick={counterStore.increment}>Increment</button>
<button onClick={counterStore.decrement}>Decrement</button>
</div>
);
});
export default Counter;
六、生命周期 (Life)
根据 创建 挂载 更新 销毁 四个阶段来进行
Vue (3.0)
示意图
![](/files/attmgn/2024/7/admin20240725010153996_2.jpg)
1、setup()
在组件实例化时调用,用于设置组件的状态和响应式数据。
挂载
2、 onBeforeMount()
在组件挂载前调用,可以进行一些准备工作。
3、onMounted()
在组件挂载后调用,通常用于执行异步请求或订阅事件。
更新
4、onBeforeUpdate()
在组件更新前调用,可以进行一些准备工作。
5、onUpdated()
在组件更新后调用,通常用于处理更新后的 DOM 操作或执行一些副作用。
卸载
6、onBeforeUnmount()
在组件卸载前调用,用于清理定时器、取消订阅等操作。
7、onUnmounted()
在组件卸载后调用,用于执行一些清理工作。
React (18.0)
示意图
![](/files/attmgn/2024/7/admin20240725010154628_3.jpg)
初始化
1、constructor()
组件实例化时调用,用于初始化状态和绑定方法
2、componentWillMount()
组件初始化时只调用,以后组件更新不调用,整个生命周期只调用一次,此时可以修改state。
挂载
3、 render()
react最重要的步骤,创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。
4、componentDidMount()
组件渲染之后调用,只调用一次。
更新
5、componentWillReceiveProps(nextProps)
组件初始化时不调用,组件接受新的props时调用。
6、shouldComponentUpdate(nextProps, nextState)
组件接受新的state或者props时调用,我们可以设置在此对比前后两个props和state是否相同,如果相同则返回false阻止更新,因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候。需要注意的是,shouldComponentUpdate()
返回true
,则组件将会重新渲染在使用 shouldComponentUpdate()
方法时,开发者需要谨慎操作,确保逻辑正确,避免出现意外的渲染结果。
7、componentWillUpdata(nextProps, nextState)
组件初始化时不调用,只有在组件将要更新时才调用,此时可以修改state
8、render()
组件渲染
9、componentDidUpdate()
组件初始化时不调用,组件更新完成后调用,此时可以获取dom节点。
4、卸载
10、componentWillUnmount()
组件将要卸载时调用,一些事件监听和定时器需要在此时清除。
关于React函数组件
在 React 中,函数组件没有传统的生命周期方法,但是引入了 React Hooks 来管理函数组件的状态和副作用。Hooks 提供了一组函数,可以在函数组件内部使用来实现类组件中的生命周期功能。
以下是一些常用的 React Hooks,可以用来模拟生命周期行为:
useState
:用于在函数组件中创建和管理状态。useEffect
:在组件渲染完成后执行副作用操作,相当于类组件中的 componentDidMount
、componentDidUpdate
和 componentWillUnmount
的结合。useLayoutEffect
:在组件渲染完成后,DOM 更新之前执行副作用操作,类似于 useEffect
,但在浏览器执行绘制之前同步执行。useContext
:用于访问 React 的上下文(Context)。useReducer
:类似于 Redux 中的 reducer
,用于管理复杂的状态逻辑。useCallback
:用于缓存回调函数,以便在依赖项不变时避免重新创建回调函数。useMemo
:用于缓存计算结果,以便在依赖项不变时避免重新计算。useRef
:用于在函数组件的多次渲染之间存储可变值。
使用这些 Hooks,可以在函数组件中实现类组件的生命周期行为。例如,使用 useEffect
可以在组件挂载、更新和卸载时执行相应的副作用操作,使用 useState
可以创建和管理组件的状态。
注意函数组件的 Hooks 必须在函数组件的顶层调用,不能在条件语句、循环或嵌套函数中使用。这是为了确保 Hooks 的调用顺序始终保持一致。虽然函数组件没有传统的生命周期方法,但通过使用 React Hooks,可以在函数组件中模拟生命周期行为并实现相应的功能。
七、怎么选择 (choose)
1、编程风格来看,vue的模板语法贴近于 html,所以在学习初的时候更容易被接受。react的编写方式则是更灵活一些。
2、官方功能实现,Vue的魔改较多。是方便了统一?还是被限制住了?react功能实现除了基本的,都要自己造轮子。是灵活发挥?还是容易造成质量不一?
3、都是广泛被前端使用的主流框架之一, 只为更好更高效的实现前端效果。
用 合适
和 需求
两个词来形容多者间的选择关系,最好不过了。无非对于这个需求,刚好合适。
对于文章内容有什么指点,欢迎评论留言,也更加欢迎JYM留下更为深层次关于对比的看法。
最后,给JYM两个数据魑慰�
下载累计
查询入口:npm-stat.com/[5]
Vue 每月平均下载量 1700w 左右,2023 年累计下载量:199,055,201(2 亿)。
![](/files/attmgn/2024/7/admin20240725010154768_4.jpg)
React 每月平均下载量 8500w 左右,2023 年累计下载量:1,025,630,896(10.2 亿+)
![](/files/attmgn/2024/7/admin20240725010155040_5.jpg)
学习难度
vue 前期学习难度前期可能没那么大,后期的进度就要缓慢一点
![](/files/attmgn/2024/7/admin20240725010155288_6.jpg)
react 前期学习难度可能大一些,后期的难度就越来越小
![](/files/attmgn/2024/7/admin20240725010155700_7.jpg)
该文章在 2024/7/25 9:50:21 编辑过