React与Vue:现在使用ReactHooksVue3CompositionAPI!ReactvsVue:传奇还在继续几年前,我决定尝试在React和Vue中构建一个相当标准的ToDo应用程序。这两个应用程序都是使用默认CLI构建的(React的create-react-app和Vue的vue-cli)。我的目的是编写公正的内容,并概述如何使用这两种技术执行某些任务。当ReactHooks发布时,我在原始文章中附加了“2019版”,它用FunctionalHooks取代了ClassComponents的使用。随着Vue版本3及其组件API的发布,是时候用“2020版本”再次更新本文了。让我们快速看一下这两个应用程序的外观:两个应用程序的CSS代码完全相同,但它们的位置不同。考虑到这一点,让我们看一下这两个应用程序的文件结构:最终,它们都实现了相同的目标,没什么好说的,你不能继续在React或Vue中以不同的方式构建你的文件。这真的取决于个人喜好。你会从开发者社区听到很多关于CSS结构的讨论,尤其是React,因为有很多CSS-in-JS解决方案,比如styled-components和emotions。顺便说一下,CSS-in-JS的字面意思就是这个意思。虽然这些功能很有用,但到目前为止,我们只会遵循两个CLI中概述的结构。但在继续之前,让我们快速浏览一下典型的Vue和React组件是什么样的:我们如何改变数据?但首先,“变异数据”到底是什么意思?听起来有点技术性?基本上,它只是意味着改变我们存储的数据。因此,如果我们想将一个人的名字的值从John更改为Mark,我们将“改变数据”。所以,这就是React和Vue之间的关键区别所在。Vue本质上创建了一个可以自由更新数据的数据对象,而React通过状态挂钩来处理这个问题。让我们看看下面两张图片中的设置,我们将解释发生了什么:Reactstate:Vuestate:所以你可以看到我们向两者传递了相同的数据,但是结构有点不同。使用React,或者至少从2019年开始,我们通常通过一系列Hook来处理状态。如果您以前没有见过这样的概念,起初它们可能看起来有点奇怪。基本上,它是这样工作的:假设我们要创建一个待办事项列表。我们可能需要创建一个名为list的变量,它可以接受一个字符串或对象数组(例如,如果我们想给每个待办事项字符串一个ID和其他一些东西,我们可以通过编写const[list,setList]=useState([])。这里我们使用了React称之为Hook的东西——叫做useState。这基本上允许我们在我们的组件中保持本地状态。另外,你可能已经注意到我们在useState()内部使用它一个空数组[]被传入。我们放在那里的是我们希望列表初始设置的内容,在我们的例子中,是一个空数组。但是,正如您从上图中看到的那样,我们在数组内部传入一些数据,最终成为列表的初始化数据。想知道setList的作用吗?稍后会详细介绍!在Vue中,通常将组件的所有变量数据放在返回对象的setup()函数中包含要公开的数据和功能(这基本上意味着您希望能够在您的应用程序中使用的东西)。您会注意到应用程序中的每条状态数据(即我们希望能够改变的数据)都包含在ref()函数中。这个ref()函数是我们从Vue导入的,以允许我们的应用程序在这些数据发生更改或更新时进行更新。简而言之,如果您想在Vue中创建可变数据,请将变量分配给ref()函数并将任何默认数据放入其中。那么我们如何在应用程序中引用可变数据呢?好吧,假设我们有一些名为name的数据,它被赋予了Sunil的值。在React中,因为我们使用useState()创建较小的状态,所以我们很可能已经创建了一些类似const[name,setName]=useState('Sunil')的东西。在我们的应用程序中,我们将通过简单地调用名称来引用相同的数据。现在,这里的主要区别是我们不能简单地写name='John',因为React有适当的限制来防止发生这种简单的、任意的突变。所以,在React中,我们会写setName('John')。这是setName位发挥作用的地方。基本上,在const[name,setName]=useState('Sunil')中,它会创建两个变量,一个变量将是constname='Sunil',第二个constsetName被分配一个函数,函数可以重新创建名称新的。价值。在Vue中,它位于setup()函数内部,称为constname=ref('Sunil')。在我们的应用程序中,我们将通过调用name.value来引用它。使用Vue,如果我们想使用在ref()函数中创建的值,我们将在变量上查找.value而不是简单地调用变量。换句话说,如果我们想要保存状态的变量的值,我们将寻找name.value而不是name。如果你想更新name的值,你可以通过更新name.value来实现。例如,假设我想将我的名字从Sunil更改为John。我可以通过编写name.value="John"来做到这一点。我不确定被称为John是什么感觉,但是,嘿,它发生了!实际上,React和Vue在这里做着同样的事情,创建可以更新的数据。每当更新包含在ref()函数中的数据时,Vue基本上默认结合自己的name和setName版本。React要求您使用内部值调用setName()来更新状态,如果您尝试更新数据对象中的值,Vue会假设您这样做了。那么,为什么React还要将值和函数分开呢?为什么还要使用useState()?本质上,React希望能够在状态发生变化时重新运行某些生命周期挂钩。在我们的示例中,如果调用setName(),React将知道某些状态已更改,因此可以运行这些生命周期挂钩。如果你直接改变状态,React将不得不做更多的工作来跟踪变化和运行生命周期挂钩等。现在我们有了一些解决方法,让我们通过查看如何将新项目添加到两个“待办事项”来更详细地了解.我们如何创建新的待办事项?反应:constcreateNewToDoItem=()=>{constnewId=generateId();constnewToDo={id:newId,text:toDo};setList([...list,newToDo]);setToDo("");};React是如何制作的?在React中,我们的输入字段有一个名为value的属性。每次通过onChange事件侦听器更改其值时,该值都会自动更新。JSX(基本上是HTML的一种变体)看起来像这样:它更新状态。handleInput函数如下所示:constandleInput=(e)=>{setToDo(e.target.value);};现在,只要用户按下页面上的+按钮添加新项目,就会触发createNewToDoItem函数。让我们再看看这个函数,看看发生了什么:constcreateNewToDoItem=()=>{constnewId=generateId();constnewToDo={id:newId,text:toDo};setList([...list,newToDo]);setToDo("");};本质上,newId函数基本上是创建一个新的ID,该ID将提供给我们的新待办事项。newToDo变量是一个对象,其ID键的值为newId。它还有一个文本键,将toDo的值作为它的值。这与输入值更改时更新的toDo相同。然后我们用完setList函数并传入一个包含整个列表以及新创建的newToDo的数组。如果...列表位看起来很奇怪,开头的三个点称为展开运算符,它基本上将列表中的所有值作为单个项传递,而不是简单地将完整项作为数组传递。困惑?如果是这样,我强烈推荐阅读Scatter,因为它很棒!无论如何,最后我们运行setToDo()并传入一个空字符串。这样,我们的输入值为空,我们可以输入一个新的toDos。Vue:functioncreateNewToDoItem(){constnewId=generateId();list.value.push({id:newId,text:todo.value});todo.value="";}Vue是怎么做到的呢?在Vue中,输入字段上有一个名为v-model的句柄。这允许我们做一些叫做双向绑定的事情。让我们快速浏览一下输入字段并解释发生了什么:
