我用Vue和React构建了相同的应用程序,这是他们的差异

本文通过构建相同的待办事项应用,对比了React与Vue在实际开发中的差异,包括数据更改、新待办事项创建、待办事项删除等方面的不同实现。

在工作中使用了Vue之后,我已经对它有了相当深入的了解。同时,我也对React感到好奇。我阅读了React的文档,也看了一些教程视频,虽然它们很棒,但我真正想知道的是React与Vue有哪些区别。这里所说的区别,并不是指它们是否都具有虚拟DOM或者它们如何渲染页面。我真正想要做的是对它们的代码进行并排比较,并搞清楚在使用这两个框架开发应用时究竟有哪些差别。

\\

我决定构建一个标准的待办事项应用程序,用户可以添加和删除待办事项。我分别使用它们默认的CLI(React的create-react-app和Vue的vue-cli)来创建这个应用。先让我们看一下这两个应用的外观:

\\

51e5f7171ffbecd8f6fd677c9e4092ed.png

\\

两个应用程序的CSS代码几乎完全相同,但代码存放的位置存在差别。

\\

84304fe90f4b1adca7ba04a82e32947c.png

\\

它们的结构也几乎完全相同,唯一的区别是React有三个CSS文件,而Vue则没有。这是因为React组件需要一个附带的文件来保存样式,而Vue采用包含的方式,将样式声明在组件文件中。

\\

从理论上讲,你可以使用老式的style.css文件来保存整个页面的样式,这完全取决于你自己。不管怎样,还是展示一下.vue文件中的CSS代码长什么样:

\\

6129601263f3a7b40a468d61c4271e3b.png

\\

看完样式方面的问题,现在让我们深入了解其他细节!

\\

我们如何改变数据?

\\

我们说“改变数据”(mutate data),实际上就是指修改已经保存好的数据。比如,如果我们想将一个人的名字从John改成Mark,我们就要“改变数据”。这就是React和Vue的关键区别之一。Vue创建了一个数据对象,我们可以自由地更新数据对象,而React创建了一个状态对象,要更新状态对象,需要做更多琐碎的工作。下面是React的状态对象和Vue的数据对象之间的对比:

\\

2734d35acd5003eb92530cdb99eb8cbf.png

\\

React的状态对象

\\

bf256a8c356dff7e0e133c216ba0bec0.png

\\

Vue的数据对象

\\

从图中可以看到,我们传入的是相同的数据,它们只是标记的方式不一样。但它们在如何改变这些数据方面却有很大的区别。

\\

假设我们有一个数据元素name:'Sunil'。

\\

在Vue中,我们通过this.name来引用它。我们也可以通过this.name='John'来更新它,这样会把名字改成John。

\\

在React中,我们通过this.state.name来引用它。关键的区别在于,我们不能简单地通过this.state.name='John'来更新它,因为React对此做出了限制。在React中,我们需要使用this.setState({name:'John'})的方式来更新数据。

\\

在了解了如何修改数据之后,接下来让我们通过研究如何在待办事项应用中添加新项目来深入了解其他细节。

\\

我们如何创建新待办事项?

\\

React:

\\
\createNewToDoItem = () =\u0026gt; {\    this.setState( ({ list, todo }) =\u0026gt; ({\      list: [\          ...list,\        {\          todo\        }\      ],\      todo: ''\    })\  );\};
\\

Vue:

\\
\createNewToDoItem() {\    this.list.push(\        {\            'todo': this.todo\        }\    );\    this.todo = '';\}
\\

React是怎么做到的?

\\

在React中,input有一个叫作value的属性。我们通过几个与创建双向绑定相关的函数来自动更新value。React通过为input附加onChange函数来处理双向绑定。

\\
\\u0026lt;input type=\"text\" \       value={this.state.todo} \       onChange={this.handleInput}/\u0026gt;
\\

只要input的值发生变化,就会执行handleInput函数。这个函数会将状态对象中todo字段的值改为input中的值。这个函数看起来像这样:

\\
\handleInput = e =\u0026gt; {\  this.setState({\    todo: e.target.value\  });\};
\\

现在,只要用户按下页面上的+按钮,createNewToDoItem就会调用this.setState,并传入一个函数。这个函数有两个参数,第一个是状态对象的list数组,第二个是todo(由handleInput函数更新)。然后函数会返回一个新对象,这个对象包含之前的整个list,然后将todo添加到list的末尾。

\\

最后,我们将todo设置为空字符串,它也会自动更新input中的值。

\\

Vue是怎么做到的?

\\

在Vue中,input有一个叫作v-model的属性。我们可以用它来实现双向绑定。

\\
\\u0026lt;input type=\"text\" v-model=\"todo\"/\u0026gt;
\\

v-model将input绑定到数据对象toDoItem的一个key上。在加载页面时,我们将toDoItem设置为空字符串,比如todo:’’。如果todo不为空,例如todo:’add some text here',那么input就会显示这个字符串。我们在input中输入的任何文本都会绑定到todo。这实际上就是双向绑定(input可以更新数据对象,数据对象也可以更新input)。

\\

因此,回看之前的createNewToDoItem()代码块,我们将todo的内容放到list数组中,然后将todo更新为空字符串。

\\

我们如何删除待办事项?

\\

React:

\\
\deleteItem = indexToDelete =\u0026gt; {\    this.setState(({ list }) =\u0026gt; ({\      list: list.filter((toDo, index) =\u0026gt; index !== indexToDelete)\    }));\};
\\

React是怎么做到的?

\\

虽然deleteItem函数位于ToDo.js中,我仍然可以在ToDoItem.js中引用它,就是将deleteItem()函数作为\u0026lt;ToDoItem/\u0026gt;的prop传入:

\\
\\u0026lt;ToDoItem deleteItem={this.deleteItem.bind(this, key)}/\u0026gt;
\\

这样可以让子组件访问传入的函数。我们还绑定了this和参数key,传入的函数需要通过key来判断要删除哪个ToDoItem。在ToDoItem组件内部,我们执行以下操作:

\\
\\u0026lt;div className=”ToDoItem-Delete” onClick={this.props.deleteItem}\u0026gt;-\u0026lt;/div\u0026gt; 
\\

我使用this.props.deleteItem来引用父组件中的函数。

\\

Vue:

\\
\this.$on(‘delete’, (event) =\u0026gt; {\    this.list = this.list.filter(item =\u0026gt; item.todo !== event)\})
\\

Vue是怎么做到的?

\\

Vue的方式稍微有点不同,我们基本上要做三件事。

\\

首先,我们需要在元素上调用函数:

\\
\\u0026lt;div class=”ToDoItem-Delete” @click=”deleteItem(todo)”\u0026gt;-\u0026lt;/div\u0026gt;
\\

然后我们必须创建一个emit函数作为子组件内部的一个方法(在本例中为ToDoItem.vue),如下所示:

\\
\deleteItem(todo) {\this.$parent.$emit(‘delete’, todo)\}
\\

然后我们的父函数,也就是this.$on(’delete’)事件监听器会在它被调用时触发过滤器函数。

\\

简单地说,React中的子组件可以通过this.props访问父函数,而在Vue中,必须从子组件中向父组件发送事件,然后父组件需要监听这些事件,并在它被调用时执行函数。

\\

这里值得注意的是,在Vue示例中,我也可以直接将$emit部分的内容写在@click监听器中,如下所示:

\\
\ \u0026lt;div class=”ToDoItem-Delete” @click=”this.$parent.$emit(‘delete’, todo)”\u0026gt;-\u0026lt;/div\u0026gt; 
\\

这样可以减少一些代码,不过也取决于个人偏好。

\\

我们如何传递事件监听器?

\\

React:

\\

简单事件(如点击事件)的事件监听器很简单。以下是我们为添加新待办事项的按钮创建click事件的示例:

\\
\\u0026lt;div className=”ToDo-Add” onClick={this.createNewToDoItem}\u0026gt;+\u0026lt;/div\u0026gt;
\\

非常简单,看起来很像是使用纯JS处理内联的onClick事件。而在Vue中,需要花费更长的时间来设置事件监听器。input标签需要处理onKeyPress事件,如下所示:

\\
\\u0026lt;input type=”text” onKeyPress={this.handleKeyPress}/\u0026gt;
\\

只要用户按下了'enter'键,这个函数就会触发createNewToDoItem函数,如下所示:

\\
\handleKeyPress = (e) =\u0026gt; {\if (e.key === ‘Enter’) {\this.createNewToDoItem();\}\};
\\

Vue:

\\

在Vue中,要实现这个功能非常简单。我们只需要使用@符号和事件监听器的类型。例如,要添加click事件侦听器,我们可以这样写:

\\
\\u0026lt;div class=”ToDo-Add” @click=”createNewToDoItem()”\u0026gt;+\u0026lt;/div\u0026gt; 
\\

注意:@click实际上是写v-on:click的简写。在Vue中,我们可以将很多东西链接到事件监听器上,例如.once可以防止事件监听器被多次触发。在编写用于处理按键特定事件侦听器时,还可以使用一些快捷方式。我发现,在React中为添加待办事项按钮创建一个事件监听器需要花费更长的时间。而在Vue中,我可以简单地写成:

\\
\\u0026lt;input type=”text” v-on:keyup.enter=”createNewToDoItem”/\u0026gt;
\\

我们如何将数据传给子组件?

\\

React:

\\

在React中,当创建子组件时,我们将props传给它。

\\
\\u0026lt;ToDoItem key={key} item={todo} /\u0026gt;
\\

我们将todo props传给了ToDoItem组件。从现在开始,我们可以在子组件中通过this.props引用它们。因此,要访问item.todo,我们只需调用this.props.todo。

\\

Vue:

\\

在Vue中,当创建子组件时,我们将props传给它。

\\
\\u0026lt;ToDoItem v-for=\"item in this.list\"\          :todo=\"item.todo\"\          :key=\"list.indexOf(item)\"\          :id=\"list.indexOf(item)\"\\u0026gt;\\u0026lt;/ToDoItem\u0026gt;
\\

然后,我们将它们加入到子组件的props数组,如:props:[‘id’,'todo']。然后可以在子组件中通过名字来引用它们,入'id'和'todo'。

\\

我们如何将数据发送回父组件?

\\

React:

\\

我们在调用子组件时将函数作为prop传给子组件,然后通过任意方式调用子组件的函数,这将触发位于父组件中的函数。我们可以在“如何删除待办事项”一节中看到整个过程的示例。

\\

Vue:

\\

在我们的子组件中,我们只需写一个函数,让它向父函数发回一个值。在父组件中,我们写了一个函数来监听这个值,然后触发函数调用。我们可以在“如何删除待办事项”一节中看到整个过程的示例。

\\

示例代码链接:

\\

Vue:https://github.com/sunil-sandhu/vue-todo

\\

React:https://github.com/sunil-sandhu/react-todo

\\

英文原文:https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-e9a1ae8077fd

\\

感谢覃云对本文的审校。

<think>嗯,用户让我介绍一下VueReact相同不同点。首先,我需要回忆这两个框架的基本信息,确保自己理解正确。然后,我需要组织信息,让结构清晰,符合用户要求的步骤式解答。 首先,它们的相同点。都是用于构建用户界面的JavaScript框架,都采用组件化开发,这点很重要。虚拟DOM应该也是一个共同点,因为两者都用来优化性能。还有响应式数据绑定,虽然实现方式不同,但目标一致。生态系统方面,两者都有丰富的周边工具库,比如路由、状态管理,这也是共同之处。跨平台能力,比如React NativeVue的NativeScript,应该也算。 接下来是不同点。首先是设计理念,Vue更注重渐进式易用性,而React推崇函数式组合。然后是语法,Vue的模板语法React的JSX可能是一个主要区别。数据绑定方面,Vue是双向的,React是单向的,需要明确处理状态变化。状态管理,VueVuex,React有Redux或Context API。API设计上,Vue更倾向于提供更多内置功能,React则保持精简,依赖社区。学习曲线,Vue可能对新手更友好,而React需要更多概念理解,比如HooksImmutable数据。 然后需要考虑用户可能的背景。他们可能是前端开发者,想选择合适的技术栈,或者面试需要比较两者。用户可能希望了解核心差异适用场景,比如项目规模、团队经验等。需要确保回答真实可靠,引用常见用例,比如Vue适合中小型项目,React适合复杂应用。 还要检查有没有遗漏的关键点,比如生态系统的具体例子,比如Vue RouterReact Router,或者VuexRedux。性能方面可能也需要提及,虽然两者都高效,但优化策略不同。另外,社区支持,React由Facebook维护,Vue由个人团队维护,这可能影响长期维护的信心。 需要确保语言口语化,但结构清晰,分点列出。同时注意用户提到的系统级指令,比如数学公式的格式,但这里可能用不上。不过要确保其他格式要求,比如中文回答,结构分相同不同点,每部分用编号列表,可能加粗标题。 最后,总结部分要简明,帮助用户根据项目需求做选择。可能还需要提到组合式API(Vue 3)Hooks(React 16.8+)的对比,这是较新的特性,展示框架的发展趋势。 检查是否有错误,比如Vue是否是双向数据绑定,React的单向数据流是否正确。是的,Vue支持v-model双向绑定,而React通过stateprops单向传递。状态管理库名称是否正确,VuexRedux都是正确的。还有语法示例是否正确,比如Vue的模板React的JSX。 确保回答没有技术错误,结构符合要求,分点清晰,帮助用户逐步理解两者的异同。可能需要调整顺序,把最重要的点放在前面,比如设计理念语法差异。同时保持客观,不偏袒任何一方,指出各自的优缺点。</think>### Vue React相同点与不同点 #### 一、相同点 1. **核心目标** 均为构建用户界面的现代化前端框架,专注于通过组件化开发模式提升开发效率可维护性。 2. **虚拟 DOM** 两者都通过虚拟 DOM 技术优化性能: - 虚拟 DOM 是内存中的轻量级 DOM 表示,减少直接操作真实 DOM 的开销。 - 通过 Diff 算法比对变化,仅更新必要的 DOM 节点。 3. **响应式数据驱动** - 数据变化自动触发视图更新(如 Vue 的 `data` React 的 `state`)。 - 开发者无需手动操作 DOM。 4. **生态系统** 提供完整的配套工具链: - **路由**:Vue Router vs React Router。 - **状态管理**:Vuex/Pinia vs Redux/MobX。 - **服务端渲染**:Nuxt.js vs Next.js。 5. **跨平台能力** 支持多端开发: - **移动端**:Vue Native/NativeScript vs React Native。 - **桌面端**:Electron 均适用。 --- #### 二、不同点 1. **设计理念** - **Vue**:渐进式框架,强调简单易用。 - 逐步集成特性(如直接通过 `<script>` 引入)。 - 提供更多开箱即用功能(如模板语法、指令)。 - **React**:函数式编程思想,强调组合与灵活性。 - 仅关注视图层,其他功能依赖社区方案(如路由、状态管理)。 - 推崇“Learn Once, Write Anywhere”。 2. **语法风格** - **Vue**:基于 HTML 的模板语法。 ```html <template> <button @click="count++">{{ count }}</button> </template> ``` - **React**:JSX(JavaScript 语法扩展)。 ```jsx function Counter() { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}>{count}</button>; } ``` 3. **数据绑定** - **Vue**:支持双向绑定(如 `v-model`)。 ```html <input v-model="message"> ``` - **React**:严格单向数据流,需手动处理事件。 ```jsx <input value={message} onChange={(e) => setMessage(e.target.value)} /> ``` 4. **状态管理** - **Vue**:官方推荐 Vuex(Vue 2)或 Pinia(Vue 3)。 ```javascript // Pinia 示例 const store = defineStore('counter', { state: () => ({ count: 0 }), actions: { increment() { this.count++ } } }); ``` - **React**:依赖第三方库(如 Redux、Zustand)或 Context API。 ```javascript // Redux 示例 const slice = createSlice({ name: 'counter', initialState: 0, reducers: { increment: (state) => state + 1 } }); ``` 5. **API 设计** - **Vue**: - 选项式 API(Vue 2):通过 `data`、`methods` 等对象组织代码。 - 组合式 API(Vue 3):类似 React Hooks,支持逻辑复用。 ```javascript setup() { const count = ref(0); const increment = () => count.value++; return { count, increment }; } ``` - **React**: - 类组件(旧版)与函数组件 + Hooks(主流)。 ```javascript useEffect(() => { /* 副作用逻辑 */ }, [deps]); ``` 6. **学习曲线** - **Vue**:模板语法更接近传统 HTML,适合新手快速上手。 - **React**:需理解 JSX、Hooks 及函数式编程概念,入门门槛略高。 --- #### 三、适用场景 - **选择 Vue**: - 中小型项目或需要快速原型开发。 - 偏好声明式模板与内置功能(如过渡动画、指令)。 - **选择 React**: - 大型复杂应用或需要高度定制化。 - 团队熟悉函数式编程或已有 React 生态经验。 #### 四、总结 Vue React 均能高效构建现代 Web 应用,差异主要体现在设计哲学与实现方式。**Vue 更强调简化开发流程**,而 **React 更注重灵活性与控制力**。实际选择需结合团队习惯、项目规模及长期维护需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值