文章目录
前言
Vue和 React是市面上目前非常受欢迎的两个前端框架。它们都采用了组件化的开发模式,使得开发者可以将复杂的应用拆分为多个小组件进行开发,从而提高了代码的可维护性和重用性。然而,虽然Vue 和React都拥有各自的优点,但它们也存在着一些不同之处,本文来讲述一下Vue 和React 中开发的区别(后续在持续更新)
1.创建项目
Vue
在Vue3更新为正式版本后,Vue官方项目创建改为了 vite
-
Vite
-
创建项目 -
npm create vue@latest
-
个人需求进行选择添加-ts,jsx,router,pinia,单元测试,eslint,prettier等等
-
-
@vue/cli
-
vue/cli 是通过webpack 创建项目
-
安装 vue/cli -
npm install -g @vue/cli
-
通过 vue -V 查看安装版本 -
vue -V
-
创建项目 -
vue create 项目名称
-
之后按照个人需求安装
React
-
npx ,官网推荐(有点慢)
-
创建项目 -
npx create-react-app 项目名称
-
vite
-
创建项目 -
npm create vite@latest
-
umi - https://v3.umijs.org/zh-CN
-
umi是蚂蚁集团的底层前端框架,其中内置了路由,构建,部署测试等等
-
安装umi-
npm install -g @umijs/cli
-
创建项目 -
umi-create 项目名称
2.写法风格
Vue
vue使用类似于HTML的模版语法慢,贴近HTML,学习成本低,但有时候不够灵活
使用基于 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>
react
react使用JSX语法,类似于js,限制比较多,(组件名要大写,属性要驼峰,单标签要闭合等等),但是可以跟模版语法很好的结合
import React, { useState } from 'react';
function App() {
const [message, setMessage] = useState('Hello, React!');
const handleClick = () => {
alert('hello Button!');
};
return (
<div>
<p>{message}</p>
<button onClick={handleClick}>Click me</button>
</div>
);
}
export default App;
3.基础语法
条件渲染
vue中通过 v-if v-show
用来条件渲染元素
<div v-if="isShown">这个元素会根据 isShown 的值进行条件渲染</div>
react中使用条件语句来实现条件渲染-例如 if && 三元
{isShown && <div>这个元素会根据 isShown 的值进行条件渲染</div>}
{isShown ? <div>这个元素会根据 isShown 的值进行条件渲染</div>:""}
在使用三元判断时,判断条件如果是 数字 0,而且没有渲染任何内容的话,那么要注意页面中将会渲染 0 出现
列表渲染
vue 中使用 v-for
用于数组或者对象的数据来循环渲染元素。可以遍历数组或者对象的每一项
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
react中列表渲染借助来js中的 map 函数来遍历数组或者对象,并返回相应的元素
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
属性绑定
vue中使用指令 v-bind
简写为:
来动态绑定属性或者表达式到元素上,可以将数据绑定到元素的属性,样式
<img :src="imageSrc" :alt="">
<img :src="imageSrc ? imageSrc :''" :alt="">
行内样式绑定
react 中可以直接使用 JS 表达式来动态设置元素的属性
<img src={imageUrl ? imageUrl : "" } alt={""} />
<img src={imageUrl} alt={""} style={{showStyle? style :'' }} />
<img src={imageUrl} alt={""} style={{width:showStyle ? "100px":"0px" }} />
事件处理
vue中使用指令v-on
简写为@
用于监听DOM事件并触发相应的方法。它可以将方法绑定到元素的事件上
<button v-on:click="handleClick">点击我触发 handleClick 方法</button>
在React中,可以直接将事件处理函数指定为元素的属性。使用箭头函数或绑定this来确保正确的上下文
<button onClick={handleClick}>点击我触发 handleClick 方法</button>
<button onClick={()=> handleClick() }>点击我触发 handleClick 方法</button>
<button onClick={()=>{
// 业务逻辑
}}>点击我触发 handleClick 方法</button>
表单双向绑定
vue中使用指令v-model
用于中在表单元素和应用程序状态之间创建双向数据绑定。它可以将表单元素的值与Vue实例中的数据进行同步
<input v-model="message" type="text">
react中,可以通过将表单元素的值与组件的状态(state)进行绑定,使用onchange事件来更新状态。
const [message,setMessage] = useState("")
<input value={message} onChange={(e) => setMessage(e.target.value)}
type="text" />
数据监听
vue
<!-- vue3 -->
setup () {
let sum = ref(0);
let msg = ref("你好");
let person = reactive({
name: "张三",
age: 18,
});
// 情况一: 监听 ref 定义的一个响应式数据
watch(sum, (val, old) => {
console.log(val, old);
});
//情况二: 监听多个响应式数据->返回数据通用是数组格式
watch(
[sum, msg],
(val, old) => {
console.log(val, old);
},
{ immediate: true, deep: true }
);
// 情况三 监听 reactive 定义的响应式数据
watch([person, sum], (val, old) => {
console.log("val", val, old);
});
return { sum, msg, person };
},
// vue2
watch: {
// 情况一,简写
sum(val, old) {
console.log(val, old);
},
//情况二
sum: {
// immediate 立即监听
immediate: true,
// deep:开启为深度监视
deep: true,
handler(val, old) {
console.log(val, old);
},
},
},
react
react hook 中使用useEffect
监听数据变化
import react,{useEffect} from "react"
let num = 0
useEffect(()=>{
// 当num 发生变化后执行
},[num])
5.组件
组件通信
Vue
react
Vue 和react 组件的不同点
内容分发
vue 中使用插槽进行接收
react中没有插槽的概念,react中使用 props.children
属性用来显示父组件在子组件中需要显示内容
keep-alive
6.状态管理
Vue
Vue采用 Vuex / Pinia
进行状态管理,Vuex 和pinia 是Vue官方设计的状态管理库,因此它们的语法都十分类似
pinia
在pinia中,数据是通过store
管理的,通过actions
进行异步操作
页面使用
<template>
<div>counter:{{ counter }}</div>
<div>doubleCount:{{ doubleCount }}</div>
<el-button @click="main.randomizeCounter()">counter(round)</el-button>
<el-button type="primary" @click="main.increment()">count++</el-button>
<div>{{ name }}</div>
<el-button @click="amend()">修改</el-button>
</template>
<!-- pinia 应用 -->
<script setup lang="ts">
import { useMain } from "@/store/home";
import { storeToRefs } from "pinia";
// 使用定义数据数据
const main = useMain();
// 将其中的数据和方法使用storeToRefs 解构出来
let { counter, name, doubleCount } = storeToRefs(main);
// 通过定义的方法修改数据
main.increment();
const amend = () => {
// 修改数据;state仓库中的数据
main.$patch((state) => {
state.counter += 10;
state.name = "zhangsan";
});
};
</script>
pinia 定义
import {defineStore} from 'pinia';
export const useMain = defineStore('main', {
// 相当于data
state: () => {
return {
// 所有这些属性都将自动推断其类型,如果推断失败可以试下 as xxx
counter: 0,
name: 'Eduardo'
};
},
// 相当于计算属性
getters: {
doubleCount: (state) => {
return state.counter * 2;
}
},
// 相当于vuex的 mutation + action,可以同时写同步和异步的代码
actions: {
increment() {
this.counter++;
},
randomizeCounter() {
setTimeout(() => {
this.counter = Math.round(100 * Math.random());
}, 0);
}
}
});
react
react中没有官方定义的状态管理库,但是有许多第三方库可供选择,例如 Redux / Mobx
Redux
在redux 中,数据是通过单向数据流进行管理的,即action -> reducer -> store -> view
redux 进行异步操作通常需要使用中间件来处理异步操作
页面使用
import { useDispatch, useSelector } from "react-redux";
import { changeNum } from "@/store/modules/counter";
const Home = () => {
// 通过useSelector 获取定义的数据
const state = useSelector((state) => state.demo);
// 修改数据的方法
const dispatch = useDispatch();
const handleIncrement = () => {
dispatch(changeNum(10));
};
return (
<div>
<button onClick={handleIncrement}>加10</button>
<span>{state.age}</span>
<button
onClick={() => {
dispatch(changeNum(5));
}}
>
加5
</button>
<hr />
</div>
);
};
export default Home;
redux 模块定义
//store/index.js 文件
import { configureStore } from '@reduxjs/toolkit'
import counterSlice from './modules/counter'
const store=configureStore({
// redux中可以定义多个仓库进行使用
reducer: { demo: counterSlice.reducer }
})
export default store
redux 模块数据定义
// store/modules/Counter.js
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: {
name: "张三",
age:18
},
reducers: {
// 改变数量的reducer
changeNum: (state, actions) => {
state.age += actions.payload;
}
}
})
// reduxjs toolkit 把reducer和actions合并在一起了
export const { changeNum } = counterSlice.actions;
// 到处reducer
export default counterSlice