使用 React 和 Vue 建立相同的应用,他们有什么差别?

在工做中应用 Vue 以后,我对它有了至关深入的理解。 不过,俗话说「外国的月亮比较圆」,我好奇「外国的」 React 是怎么样的。javascript

我阅读了 React 文档并观看了一些教程视频,虽然它们很棒,但我真正想知道的是 React 与 Vue 的不一样之处。 这里的“不一样”,并非指它们是否具备虚拟 DOM 或者它们如何渲染页面。 我但愿有人能向我解释代码并告诉我其中发生了什么! 我想找一篇能解释这些差别的文章,以便 Vue 或 React(或整个 Web 开发)的新手能够更好地理解二者之间的差别。vue

但我没有找到任何解决这个问题的方法。 因此我意识到我必须本身动手,来发现类似/不一样之处。 在作的时候,我想我会记录整个过程,以便产出一篇关于此的文章。java

我决定尝试构建一个至关标准的 To Do 应用,它容许用户添加和删除列表中的项目。 这两个应用都是使用默认的 CLI 构建的(React 的 create-react-app 和 Vue 的 vue-cli)。 BTW,CLI 表明命令行界面。react

 

好吧,这个介绍已经超出了个人预期。 咱们先快速看看两个应用的界面:git

 

 

两个应用的 CSS 代码彻底相同,不过它们所在的位置有差异。 考虑到这一点,咱们接下来看看两个应用的文件结构:github

 

你会发现它们的结构几乎彻底相同。 惟一的区别是 React 应用有三个 CSS 文件,而 Vue 应用一个都没有。 这样作的缘由是,在 create-react-app 中,React 组件会有一个附带文件来控制其样式,而 Vue CLI 采用全包方法,具体样式在实际组件文件中声明。vue-cli

最终,他们都达到了一样的目的,对于不能在 React 或 Vue 中以不一样的方式构建 CSS 的问题,目前还真没什么办法。这真的取决于我的偏好 - 你会听到开发者社区关于如何构建 CSS 的大量讨论。 如今,咱们将遵循两个 CLI 中列出的结构。数组

但在咱们进一步讨论以前,咱们先快速看一下典型的 Vue 和 React 组件的是什么样的:app

扯远了。如今让咱们开始研究细节中的细节!框架

 

 

如何变异数据?

 

首先咱们要搞清楚什么是“变异数据”? 听起来有点科技感是吧? 它基本上只是意味着改变咱们存储的数据。 所以,若是咱们想将一我的的名字取值从 John 改成 Mark,咱们就是在“变异数据”。 这就是 React 和 Vue 之间的关键区别所在。 虽然 Vue 本质上建立了一个 data 对象,对象数据能够自由更新,而 React 建立了一个 state 对象,要实现更新必须多作一点工做。 如今 React 有充分的理由实现额外的 legwork,咱们稍微深刻一下。 但首先,让咱们看看 Vue 中的 data 对象和 React 中的 state 对象:

Vue data 对象在左侧。 React state 对象在右侧。

你能够看到咱们已经将相同的数据传递到二者中,只是标记不一样。 所以,将初始数据传递到咱们的组件很是很是类似。 但正如上文提到的,咱们对这些数据的修改方式在两个框架之间有所不一样。

假设咱们有一个name 为 'Sunil'的数据元素 。

在 Vue 中,咱们经过调用 this.name 来引用它。 咱们也能够调用 this.name ='John' 来更新它。 这会把个人名字改为 John。 我不肯定被称为John的感受如何,但嘿嘿,它就是发生了!

在 React 中,咱们经过调用 this.state.name 来引用同一份数据。 如今关键的区别在于咱们不能简单地写 this.state.name='John',由于 React 作了限制来防止这种简单、无忧无虑的 mutate。 因此在 React 中,咱们会使用 this.setState({name:'John'}) 的方式来编写。

虽然这基本上与咱们在 Vue 中实现的相同,可是额外的写入是由于 Vue 基本上在每次更新数据时都会合并本身的 setState 版本。 简而言之,React 须要 setState 并传入须要更新的内部数据,而 Vue 假设当你把更新的值传入 data 对象时,你是想更新它的。那么为何 React 不肯意这样作,为何还须要 setState 呢? 让 Revanth Kumar 来为咱们解释下:

“这是由于 React 但愿在状态发生变化时从新运行某些生命周期钩子,[如] componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate。 当你调用 setState 函数时,它会知道状态已经改变了。 若是你直接改变状态,React 将须要作更多工做来跟踪更改以及运行生命周期钩子等等。因此为了简单起见,React 使用 setState。“

如今咱们已经完成了 mutations,让咱们研究下如何在咱们的 To Do 应用中添加新项目,以深刻了解细节。

 

 

如何建立新的 To Do 项

 

 

 

React:

 

React 是如何作的?

在 React 中,咱们的输入字段有一个叫 value 的属性。 这个值经过使用几个函数自动更新,这些函数结合起来会建立一个很是相似于双向绑定的东西(若是你之前从未据说过这个,你能够看看以后的 How did Vue do that 部分)。 咱们经过在 input 上添加一个 onChange事件监听器来建立这种形式的双向绑定。 咱们简单看一下 input 字段,以便你了解发生了什么:

只要 input 框的值发生更改,handleInput 函数就会运行。 它会将 input 框中的任意输入更新到 state 中的 todo。 这个函数看起来像这样:

如今,只要用户按下页面上的 + 按钮添加新 item,createNewToDoItem 函数就会运行 this.setState 并向其传递一个函数。 这个函数接收两个参数,第一个是来自状态对象的 list数组,第二个是 todo(由 handleInput 函数更新)。 该函数返回一个新对象,该对象包含以前的整个 list,而后在其末尾添加 todo。 整个列表是经过使用扩展运算符添加的(若是你以前没有看过这个 ES6 语法,Google 一下吧)。

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

 

Vue:

 

Vue 是如何作的?

在 Vue 中,咱们的 input 框有一个名为 v-model 的指令。 它容许咱们作一些称为双向绑定的事情。 咱们先看看 input 框,而后解释下发生了什么:

V-Model 将此字段的输入绑定到名为 toDoItem 的 data 对象中的 key。 当页面加载时,toDoItem 会被置为空字符串,如 todo: ''。 若是 todo 非空,例如 todo: ‘add some text here’,咱们的 input 框将加载‘add some text’。 不管如何,回到将其做为空字符串,咱们在输入字段中输入的任何文本都将绑定到 todo 的值。 这正是双向绑定(input 能够更新 data 对象,data 对象能够更新 input)。

回到前面的 createNewToDoItem() 代码块,咱们看到咱们将 todo 的内容 push 到 list 数组中,而后将 todo 更新为空字符串。

 

 

 

如何删除列表数据?

 

 

 

React:

 

React 是如何作的?

虽然 deleteItem 函数位于 ToDo.js 内部,但我能够直接在 ToDoItem.js 中引用它,首先将deleteItem() 函数做为 <ToDoItem /> 上的 prop 传递:

首先将该功能传递给子组件,使其能够被访问。 你能够看到咱们也绑定了 this 以及传递了 key 参数,由于 key 是函数将用于区分 ToDoItem 在单击时尝试删除的内容。 而后,在ToDoItem 组件内部,咱们执行如下操做:

我须要作的就是引用一个位于父组件内部的函数来引用 this.props.deleteItem

 

Vue:

 

Vue 是如何作的?

Vue 的方法稍有不一样。 咱们基本上要作三件事:

首先,在咱们想要调用函数的元素上:

而后咱们必须建立一个 emit 函数做为子组件内部的方法(在本例中为 ToDoItem.vue),以下所示:

除此以外,你会发现咱们在 ToDo.vue 中引入 ToDoItem.vue 时实际引用了一个函数

这就是所谓的自定义事件监听器。 它会监放任何使用 'delete' 字符串触发 emit 的操做。 若是监听到,它会触发一个名为 onDeleteItem 的函数。 此函数位于 ToDo.vue 内部,而不是ToDoItem.vue。 如前所述,此函数只是过滤 data 对象内的 todo 数组,以删除被点击的 item。

这里也值得注意的是,在 Vue 示例中,我能够简单地在 @click 监听器中编写 $emit 部分,以下所示:

这会将步数从 3 减小到 2,这仅仅取决于我的偏好。

简而言之,React 中的子组件能够经过 this.props 访问父组件方法(假设你正在传递 props,这是至关标准的作法,你会在其余 React 示例中遇到许屡次),而在 Vue 中, 你必须从子组件中触发由父组件全部的事件。

 

 

 

如何传递事件监听器?

 

 

React:

简单事件(如点击事件)的事件监听器是直截了当的。 如下是咱们如何为建立新 ToDo item 的按钮建立 click 事件的示例:

这里很是简单,就像咱们使用原生 JS 处理内联 onClick 同样。 正如 Vue 部分所述,在按下回车按钮的状况下设置事件监听器就须要花点时间了。 咱们能够在 input 标签中处理一下 onKeyPress 事件,以下:

只要它识别出按下了 '回车(Enter)' 键,这个函数就会触发 createNewToDoItem 函数,以下所示:
 

 

Vue:

在 Vue,它是超级直接的。 咱们只使用 @ 符号,而后使用咱们想要事件监听器的类型。 例如,要添加 click 事件侦听器,咱们能够这样:

注意:@click 其实是 v-on: click 的简写。 Vue 事件监听器的一个很酷的事情是,在它以后咱们能够链式调用许多方法,例如 .once,它能够防止事件监听器被屡次触发。 在编写用于处理键击的特定事件侦听器时,还有一些快捷方式。 我发如今按下回车按钮的状况下,在 React 中建立一个事件监听器须要花费很长时间来建立新的 ToDo item。而在Vue,我可以简单地这样写:

 

 

 

如何向子组件传递数据?

 

 

 

React:

在 react 中,咱们将 props 传递到子组件。 如:

在这里,咱们看到两个传递给 ToDoItem 组件的 props。 从如今开始,咱们就能够经过 this.props 在子组件中引用它们了。 所以,要访问 item.todo prop,咱们只需调用 this.props.item。

 

Vue:

在 Vue 中,咱们将 props 传递到子组件。 如:

完成后,咱们将它们传递给子组件中的 props 数组,如 props: ['todo']。 而后能够经过他们的名字在子组件中引用它们 - 因此在咱们的例子中,'todo'。

 

 

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

 

 

React:

咱们首先将函数传递给子组件,方法是在咱们调用子组件的位置将其引用为 prop。 而后,咱们经过引用 this.props.whateverTheFunctionIsCalled,经过任何方式(例如 onClick)添加对子函数的调用。 而后,这将触发位于父组件中的函数。 咱们能够在“如何从列表中删除”一节中看到整个过程的示例。

 

Vue:

在咱们的子组件中,咱们只需编写一个函数,将一个值发送回父函数。 在咱们的父组件中,咱们编写一个函数来侦听什么时候 emit 该值,而后能够触发函数调用。 咱们能够在“如何从列表中删除”一节中看到整个过程的示例。

 

 

大功告成!

咱们研究了如何添加,删除和更改数据,将数据以表单 props 形式从父组件传递到子组件,以及以事件侦听器的形式将数据从子组件发送到父组件。 固然,在 React 和 Vue 之间存在许多其余的小差异,但但愿本文的内容能做为理解两个框架如何处理东西的基础。

 

Github links to both apps:

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

React ToDo: 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

相关文章
相关标签/搜索