vue和react相同点_我在React和Vue中创建了完全相同的应用程序。 这是区别。 [2020年版]

本文对比了2020年Vue和React在创建相同应用程序时的异同,探讨两者之间的共同特点。
摘要由CSDN通过智能技术生成

vue和react相同点

React vs Vue:传奇继续 (React vs Vue: the saga continues)

A few years ago, I decided to try and build a fairly standard To Do App in React and Vue. Both apps were built using the default CLIs (create-react-app for React, and vue-cli for Vue). My aim was to write something that was unbiased and simply provided a snapshot of how you would perform certain tasks with both technologies.

几年前,我决定尝试在React和Vue中构建一个相当标准的To Do App。 这两个应用程序都是使用默认的CLI构建的(React的create-react-app和Vue的vue-cli)。 我的目的是编写无偏见的内容,并提供有关如何使用这两种技术执行某些任务的概述。

When React Hooks were released, I followed up the original article with a ‘2019 Edition’ which replaced the use of Class Components with Functional Hooks. With the release of Vue version 3 and its Composition API, now is the time to one again update this article with a ‘2020 Edition’.

当React Hooks发布时,我在原始文章后面加上了“ 2019 Edition ”,该版本将Class Components的使用替换为Functional Hooks。 随着Vue版本3及其组合API的发布,现在是时候再次以“ 2020版”更新本文了。

让我们快速看一下这两个应用程序的外观: (Let’s take a quick look at how the two apps look:)

The CSS code for both apps are exactly the same, but there are differences in where these are located. With that in mind, let’s next have a look at the file structure of both apps:

两个应用程序CSS代码完全相同,但是它们的位置有所不同。 考虑到这一点,接下来让我们看一下两个应用程序的文件结构:

Image for post

You’ll see that their structures are similar as well. The key difference so far is that the React app has two CSS files, whereas the Vue app doesn’t have any. The reason for this is because create-react-app creates its default React components with a separate CSS file for its styles, whereas Vue CLI creates single files that contain HTML, CSS, and JavaScript for its default Vue components.

您会看到它们的结构也很相似。 到目前为止的主要区别是React应用程序有两个CSS文件,而Vue应用程序没有任何CSS文件。 其原因是因为create-react-app使用其样式的单独CSS文件创建其默认React组件,而Vue CLI为其默认Vue组件创建包含HTML,CSS和JavaScript的单个文件。

Ultimately, they both achieve the same thing, and there is nothing to say that you can’t go ahead and structure your files differently in React or Vue. It really comes down to personal preference. You will hear plenty of discussion from the dev community over how CSS should be structured, especially with regard to React, as there are a number of CSS-in-JS solutions such as styled-components, and emotion. CSS-in-JS is literally what it sounds like by the way. While these are useful, for now, we will just follow the structure laid out in both CLIs.

最终,他们俩都能达成同一目标,而且无话可说,您不能继续在React或Vue中以不同的方式构造文件。 这确实取决于个人喜好。 您将听到来自开发人员社区的大量讨论,关于CSS的结构,尤其是关于React的结构,因为存在许多CSS-in-JS解决方案,例如样式组件和情感。 顺便说一句,CSS-in-JS的字面意义就是这样。 尽管这些功能很有用,但目前,我们将仅遵循两个CLI中列出的结构。

But before we go any further, let’s take a quick look at what a typical Vue and React component look like:

但是在进一步介绍之前,让我们快速看一下典型的Vue和React组件的外观:

A typical React file:

典型的React文件:

Image for post

A typical Vue file:

典型的Vue文件:

Image for post

Now that’s out of the way, let’s get into the nitty gritty detail!

既然这已经不成问题了,那就让我们深入了解细节吧!

我们如何突变数据? (How do we mutate data?)

But first, what do we even mean by “mutate data”? Sounds a bit technical doesn’t it? It basically just means changing the data that we have stored. So if we wanted to change the value of a person’s name from John to Mark, we would be ‘mutating the data’. So this is where a key difference between React and Vue lies. While Vue essentially creates a data object, where data can freely be updated, React handles this through what is known as a state hook.

但是首先,“突变数据”甚至意味着什么? 听起来有点技术性吗? 基本上,这只是意味着更改我们已存储的数据。 因此,如果我们想将一个人的名字的值从John更改为Mark,我们将“对数据进行变异”。 因此,这就是React和Vue之间的关键区别所在。 虽然Vue本质上创建了一个数据对象,可以在其中自由更新数据,但是React通过状态钩子来处理它。

Let’s take a look at the set up for both in the images below, then we will explain what is going on after:

让我们看一下下面两个图片中的设置,然后我们将说明发生了什么:

React state:

React状态:

Image for post

Vue state:

Vue状态:

Image for post

So you can see that we have passed the same data into both, but the structure is a bit different.

因此,您可以看到我们已经将相同的数据传递给了两者,但是结构有些不同。

With React — or at least since 2019 — we would typically handle state through a series of Hooks. These might look a bit strange at first if you haven’t seen this type of concept before. Basically, it works as follows:

使用React或至少从2019年开始,我们通常会通过一系列的Hooks处理状态。 如果您以前没有看过这种概念,那么这些一开始可能看起来有些奇怪。 基本上,它的工作方式如下:

Let’s say we want to create a list of todos. We would likely need to create a variable called list and it would likely take an array of either strings or maybe objects (if say we want to give each todo string an ID and maybe some other things. We would set this up by writing const [list, setList] = useState([]). Here we are using what React calls a Hook — called useState. This basically lets us keep local state within our components.

假设我们要创建待办事项列表。 我们可能需要创建一个名为list的变量,它可能需要一个由字符串或对象组成的数组(例如,如果我们想给每个待办事项字符串一个ID和其他一些东西,我们可以通过编写const [list, setList] = useState([])在这里,我们使用React所谓的Hook,即useState ,这基本上使我们能够在组件中保留局部状态。

Also, you may have noticed that we passed in an empty array [] inside of useState(). What we put inside there is what we want list to initially be set to, which in our case, we want to be an empty array. However, you will see from the image above that we passed in some data inside of the array, which ends up being the initialised data for list. Wondering what setList does? There will be more on this later!

另外,您可能已经注意到我们在useState()内部传入了一个空数组[] 。 我们放在其中的是我们希望列表最初设置的内容,在我们的例子中,我们希望是一个空数组。 但是,从上图可以看到,我们在数组内部传入了一些数据,这些数据最终是list的初始化数据。 想知道setList是做什么的? 稍后将对此进行更多说明!

In Vue, you would typically place all of your mutable data for a component inside of a setup() function that returns an object with the data and functions you want to expose (which basically just means the things you want to be able to make available for use in your app). You will notice that each piece of state (aka the data we want to be able to mutate) data in our app is wrapped inside of a ref() function. This ref() function is something that we import from Vue and makes it possible for our app to update whenever any of those pieces of data are changed/updated. In short, if you want to make mutable data in Vue, assign a variable to the ref() function and place any default data inside of it.

在Vue中,通常会将组件的所有可变数据放置在setup()函数内,该函数返回一个对象,其中包含要公开的数据和函数(这基本上意味着您希望能够使用的东西)在您的应用中使用)。 您会注意到,我们应用程序中的每个状态数据(也就是我们希望能够进行突变的数据)都包装在ref()函数内部。 此ref()函数是我们从Vue导入的,可让我们的应用程序在任何更改或更新这些数据时都可以更新。 简而言之,如果您想在Vue中创建可变数据,请为ref()函数分配一个变量,并将任何默认数据放入其中。

那么我们如何在我们的应用程序中引用可变数据呢? (So how would we reference mutable data in our app?)

Well, let’s say that we have some piece of data called name that has been assigned a value of Sunil.

好吧,假设我们有一些名为name的数据已被赋值为Sunil

In React, as we have our smaller pieces of state that we created with useState(), it is likely that we would have created something along the lines of const [name, setName] = useState('Sunil'). In our app, we would reference the same piece of data by calling simply calling name. Now the key difference here is that we cannot simply write name = 'John', because React has restrictions in place to prevent this kind of easy, care-free mutation-making. So in React, we would write setName('John'). This is where the setName bit comes into play. Basically, in const [name, setName] = useState('Sunil'), it creates two variables, one which becomes const name = 'Sunil', while the second const setName is assigned a function that enables name to be recreated with a new value.

在React中,由于我们使用useState()创建了较小的状态,因此很可能已经按照const [name, setName] = useState('Sunil')创建了一些东西。 在我们的应用程序中,我们将通过简单地调用name来引用相同的数据。 现在,这里的主要区别是我们不能简单地写name = 'John' ,因为React有适当的限制来防止这种简单,随意的突变产生。 因此,在React中,我们将编写setName('John') 。 这是setName位起作用的地方。 基本上,在const [name, setName] = useState('Sunil') ,它将创建两个变量,其中一个变为const name = 'Sunil' ,而第二个const setName被分配了一个函数,该函数可以使用新的名称重新创建名称。值。

In Vue, this would be sitting inside of the setup() function and would have been called const name = ref(‘Sunil'). In our app, we would reference this by calling name.value. With Vue, if we want to use the value created inside of a ref() function, we look for .value on the variable rather than simply calling the variable. In other words, if we want the value of a variable that holds state, we look for name.value, not name. If you want to update the value of name, you would do so by updating name.value. For example, let's say that I want to change my name from Sunil to John. I'd do this by writing name.value = "John". I’m not sure how I feel about being called John, but hey ho, things happen! 😅

在Vue中,它位于setup()函数内部,并且被称为const name = ref('Sunil') 。 在我们的应用程序中,我们将通过调用name.value来引用它。 使用Vue,如果我们要使用在ref()函数内部创建的值,我们将在变量上寻找.value而不是简单地调用该变量。 换句话说,如果我们想要保持状态的变量的值,我们将寻找name.value 而不是 name 。 如果要更新name的值,可以通过更新name.value 。 例如,假设我想将我的名字从Sunil更改为John。 我可以通过写name.value = "John"做到这一点。 我不确定自己被称为约翰的感觉,但是嘿,事情发生了! 😅

Effectively React and Vue are doing the same thing here, which is creating data that can be updated. Vue essentially combines its own version of name and setName by default whenever a piece of data wrappeed inside of a ref() function gets updated. React requires that you call setName() with the value inside in order to update state, Vue makes an assumption that you’d want to do this if you were ever trying to update values inside the data object. So Why does React even bother with separating the value from the function, and why is useState() even needed? Essentially, React wants to be able to re-run certain life cycle hooks whenever state changes. In our example, if setName() is called, React will know that some state has changed and can, therefore, run those lifecycle hooks. If you directly mutated state, React would have to do more work to keep track of changes and what lifecycle hooks to run etc.

实际上,React和Vue在这里做着同样的事情,即创建可以更新的数据。 Vue本质上默认会在ref()函数内部包装的一条数据被更新时默认结合其自己的name和setName版本。 React要求您使用内部值调用setName()来更新状态,如果您试图更新数据对象内部的值,Vue会假设您要这样做。 那么,为什么React甚至useState()将值与函数分开,为什么还要使用useState() ? 本质上,每当状态改变时,React都希望能够重新运行某些生命周期挂钩。 在我们的示例中,如果调用setName() ,React将知道某些状态已更改,因此可以运行这些生命周期挂钩。 如果直接改变状态,React将不得不做更多的工作来跟踪更改以及要运行的生命周期挂钩等。

Now that we have mutations out of the way, let’s get into the nitty, gritty by looking at how we would go about adding new items to both of our To Do Apps.

现在,我们已经有了一些变通的方式,让我们通过研究如何将新项目添加到两个“待办事项”应用程序中来,让我们深入了解具体情况。

我们如何创建新的待办事项? (How do we create new To Do Items?)

React: (React:)

const createNewToDoItem = () => {
const newId = generateId();
const newToDo = { id: newId, text: toDo };
setList([...list, newToDo]);
setToDo("");
};

React是如何做到的? (How did React do that?)

In React, our input field has an attribute on it called value. This value gets automatically updated every time its value changes through what is known as an onChange event listener. The JSX (which is basically a variant of HTML), looks like this:

在React中,我们的输入字段具有一个名为value的属性 每当通过onChange事件侦听器更改其值时,该值都会自动更新。 JSX(基本上是HTML的变体)如下所示:

<input
type="text"
placeholder="I need to..."
value={toDo}
onChange={handleInput}
onKeyPress={handleKeyPress}
/>

So every time the value is changed, it updates state. The handleInput function looks like this:

因此,每次更改值时,它都会更新状态。 handleInput函数如下所示:

const handleInput = (e) => {
setToDo(e.target.value);
};

Now, whenever a user presses the + button on the page to add a new item, the createNewToDoItem function is triggered. Let’s take a look at that function again to break down what is going on:

现在,每当用户按下页面上的+按钮添加新项目时,都会触发createNewToDoItem函数。 让我们再次看一下该函数以分解正在发生的事情:

const createNewToDoItem = () => {
const newId = generateId();
const newToDo = { id: newId, text: toDo };
setList([...list, newToDo]);
setToDo("");
};

Essentially the newId function is basically creating a new ID that we will give to our new toDo item. The newToDo variable is an object that takes that has an id key that is given the value from newId. It also has a text key which takes the value from toDo as its value. That is the same toDo that was being updated whenever the input value changed.

本质上, newId函数基本上是在创建一个新ID,该ID将提供给我们的新toDo项。 newToDo变量是一个具有ID密钥的对象,该ID密钥具有newId的值。 它还具有一个text键,该键将toDo中的值用作其值。 这与输入值更改时要更新的toDo相同。

We then run out setList function and we pass in an array that includes our entire list as well as the newly created newToDo.

然后,我们用完setList函数,并传入一个包含整个list以及新创建的newToDo

If the ...list, bit seems strange, the three dots at the beginning is something known as a spread operator, which basically passes in all of the values from the list but as separate items, rather than simply passing in an entire array of items as an array. Confused? If so, I highly recommend reading up on spread because it’s great!

如果...list位看起来很奇怪,则开头的三个点称为散布运算符,它基本上将list中的所有值作为单独的项目传递,而不是简单地传递完整的项目作为数组。 困惑? 如果是这样,我强烈建议您仔细阅读散布,因为它很棒!

Anyway, finally we run setToDo() and pass in an empty string. This is so that our input value is empty, ready for new toDos to be typed in.

无论如何,最后我们运行setToDo()并传入一个空字符串。 这样我们的输入值为空,可以输入新的toDos了。

Vue: (Vue:)

function createNewToDoItem() {
const newId = generateId();
list.value.push({ id: newId, text: todo.value });
todo.value = "";
}

Vue是如何做到的? (How did Vue do that?)

In Vue, our input field has a handle on it called v-model. This allows us to do something known as two-way binding. Let’s just quickly look at our input field, then we’ll explain what is going on:

在Vue中,我们的输入字段具有一个称为v-model的句柄。 这使我们能够执行称为双向绑定的操作 。 让我们快速看一下输入字段,然后说明发生了什么:

<input
type="text"
placeholder="I need to..."
v-model="todo"
v-on:keyup.enter="createNewToDoItem"
/>

V-Model ties the input of this field to a variable we created at the top of our setup() function and then exposed as a key inside of the object we returned. We haven't covered what is returned from the object much so far, so for your info, here is what we have returned from our setup() function inside of ToDo.vue:

V-Model将该字段的输入与我们在setup()函数顶部创建的变量绑定在一起,然后将其作为键公开给我们返回的对象。 到目前为止,我们还没有介绍对象返回的内容,因此,对于您的信息,这是我们从ToDo.vue内部的setup()函数返回的内容

return {
list,
todo,
showError,
generateId,
createNewToDoItem,
onDeleteItem,
displayError
};

Here, list, todo, and showError are our stateful values, while everything else are functions we want to be able to call in other places of our app. Okay, coming back out from our tangent, when the page loads, we have todo set to an empty string, as such: const todo = ref(""). If this had some data already in there, such as const todo = ref("add some text here"): our input field would load with add some text here already inside the input field. Anyway, going back to having it as an empty string, whatever text we type inside the input field gets bound to todo.value. This is effectively two-way binding - the input field can update the ref() value and the ref() value can update the input field.

在这里, listtodoshowError是我们的有状态值,而其他所有功能都是我们希望能够在应用程序其他位置调用的函数。 好的,从切线返回,当页面加载时,我们必须将todo设置为空字符串,例如: const todo = ref("") 。 如果其中已经有一些数据,例如const todo = ref("add some text here"):我们的输入字段将在输入字段内部已经添加一些文本的情况下加载。 无论如何,返回到将其作为空字符串,无论我们在输入字段中键入什么文本,都必须绑定到todo.value 。 这实际上是双向绑定-输入字段可以更新ref()值,而ref()值可以更新输入字段。

So looking back at the createNewToDoItem() code block from earlier, we see that we push the contents of todo.value into the list array - by pushing todo.value into list.value - and then update todo.value to an empty string.

所以,在看后面createNewToDoItem()从早期的代码块中,我们看到,我们推的内容todo.valuelist阵列-通过推动todo.valuelist.value -然后更新todo.value为空字符串。

We also used the same newId() function as used in the React example.

我们还使用了与React示例中相同的newId()函数。

我们如何从列表中删除? (How do we delete from the list?)

React: (React:)

const deleteItem = (id) => {
setList(list.filter((item) => item.id !== id));
};

React是如何做到的? (How did React do that?)

So whilst the deleteItem() function is located inside ToDo.js, I was very easily able to make reference to it inside ToDoItem.js by firstly, passing the deleteItem() function as a prop on as such:

因此,虽然在deleteItem()函数位于内ToDo.js,我很容易能够提及这里面通过首先ToDoItem.js,经过deleteItem()函数作为这样一个道具:

<ToDoItem key={item.id} item={item} deleteItem={deleteItem} />

This firstly passes the function down to make it accessible to the child. Then, inside the ToDoItem component, we do the following:

首先,该函数将其传递给孩子。 然后,在ToDoItem组件内部,执行以下操作:

<button className="ToDoItem-Delete" onClick={() => deleteItem(item.id)}>
-
</button>

All I had to do to reference a function that sat inside the parent component was to reference props.deleteItem. Now you may have noticed that in the code example, we just wrote deleteItem instead of props.deleteItem. This is because we used a technique known as destructuring which allows us to take parts of the props object and assign them to variables. So in our ToDoItem.js file, we have the following:

我要做的就是引用位于父组件内部的函数,就是引用props.deleteItem 。 现在您可能已经注意到,在代码示例中,我们只是编写了deleteItem而不是props.deleteItem。 这是因为我们使用了一种称为解构的技术,该技术允许我们获取props对象的一部分并将其分配给变量。 因此,在我们的ToDoItem.js文件中,我们具有以下内容:

const ToDoItem = (props) => {
const { item, deleteItem } = props;
}

This created two variables for us, one called item, which gets assigned the same value as props.item, and deleteItem, which gets assigned the value from props.deleteItem. We could have avoided this whole destructuring thing by simply using props.item and props.deleteItem, but I thought it was worth mentioning!

这为我们创建了两个变量,一个称为item,它被分配与props.item相同的值,另一个是deleteItem,它从props.deleteItem分配了值。 我们本可以通过仅使用props.item和props.deleteItem来避免整个破坏性的事情,但是我认为值得一提!

Vue: (Vue:)

function onDeleteItem(id) {
list.value = list.value.filter(item => item.id !== id);
}

Vue是如何做到的? (How did Vue do that?)

A slightly different approach is required in Vue. We essentially have to do three things here:

Vue中需要一种稍微不同的方法。 我们基本上必须在这里做三件事:

Firstly, on the element we want to call the function:

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

<button class="ToDoItem-Delete" @click="deleteItem(item.id)">
-
</button>

Then we have to create an emit function as a method inside the child component (in this case, ToDoItem.vue), which looks like this:

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

function deleteItem(id) {
emit("delete", id);
}

Along with this, you’ll notice that we actually reference a function when we add ToDoItem.vue inside of ToDo.vue:

伴随着这一点,你会发现,我们实际上引用功能 ,当我们添加ToDoItem.vue ToDo.vue内:

<ToDoItem v-for="item in list" :item="item" @delete="onDeleteItem" :key="item.id" />

This is what is known as a custom event-listener. It listens out for any occasion where an emit is triggered with the string of ‘delete’. If it hears this, it triggers a function called onDeleteItem. This function sits inside of ToDo.vue, rather than ToDoItem.vue. This function, as listed earlier, simply filters the id from the list.value array.

这就是所谓的自定义事件侦听器。 它会侦听任何使用字符串'delete'触发发射的情况。 如果听到此消息,它将触发一个名为onDeleteItem的函数。 此函数位于ToDo.vue内部,而不是ToDoItem.vue中 。 如前所述,此函数list.value数组中过滤id

It’s also worth noting here that in the Vue example, I could have simply written the $emit part inside of the @click listener, as such:

在这里还值得注意的是,在Vue示例中,我可以简单地将$emit部分写在@click侦听器内,如下所示:

<button class="ToDoItem-Delete" @click="emit("delete", item.id)">
-
</button>

This would have reduced the number of steps down from 3 to 2, and this is simply down to personal preference.

这将使步数从3减少到2,而这完全取决于个人喜好。

In short, child components in React will have access to parent functions via props (providing you are passing props down, which is fairly standard practice and you’ll come across this loads of times in other React examples), whilst in Vue, you have to emit events from the child that will usually be collected inside the parent component.

简而言之,React中的子组件将可以通过props来访问父函数(前提是您要传递props,这是相当标准的做法,在其他React示例中您会遇到大量的工作),而在Vue中,您可以从孩子发出事件,通常将其收集在父组件中。

我们如何传递事件监听器? (How do we pass event listeners?)

React: (React:)

Event listeners for simple things such as click events are straight forward. Here is an example of how we created a click event for a button that creates a new ToDo item:

简单事件(例如单击事件)的事件侦听器很简单。 这是我们如何为创建新的ToDo项目的按钮创建click事件的示例:

<button className="ToDo-Add" onClick={createNewToDoItem}>
+
</button>

Super easy here and pretty much looks like how we would handle an in-line onClick with vanilla JS. As mentioned in the Vue section, it took a little bit longer to set up an event listener to handle whenever the enter button was pressed. This essentially required an onKeyPress event to be handled by the input tag, as such:

在这里超级简单,几乎就像我们将如何使用香草JS处理嵌入式onClick。 如Vue部分所述,每当按下Enter键时,设置事件侦听器进行处理就花费了更长的时间。 这本质上需要由输入标签处理onKeyPress事件,例如:

<input
type="text"
placeholder="I need to..."
value={toDo}
onChange={handleInput}
onKeyPress={handleKeyPress}
/>

This function essentially triggered the createNewToDoItem function whenever it recognised that the ‘enter’ key had been pressed, as such:

只要该函数识别出已按下“ enter”键,便会触发createNewToDoItem函数,例如:

const handleKeyPress = (e) => {
if (e.key === "Enter") {
createNewToDoItem();
}
};

Vue: (Vue:)

In Vue it is super straight-forward. We simply use the @ symbol, and then the type of event-listener we want to do. So for example, to add a click event listener, we could write the following:

在Vue中,它非常简单明了。 我们只使用@符号,然后使用我们想要做的事件监听器的类型。 因此,例如,要添加一个click事件监听器,我们可以编写以下代码:

<button class="ToDo-Add" @click="createNewToDoItem">
+
</button>

Note: @click is actually shorthand for writing v-on:click. The cool thing with Vue event listeners is that there are also a bunch of things that you can chain on to them, such as .once which prevents the event listener from being triggered more than once. There are also a bunch of shortcuts when it comes to writing specific event listeners for handling key strokes. I found that it took quite a bit longer to create an event listener in React to create new ToDo items whenever the enter button was pressed. In Vue, I was able to simply write:

注意: @click实际上是编写v-on:click简写。 Vue事件侦听器很酷的事情是,您还可以将很多东西链接到它们,例如.once可以防止事件侦听器被多次触发。 在编写用于处理按键的特定事件侦听器时,还有许多捷径。 我发现,每当按下回车按钮时,在React中创建一个事件侦听器以创建新的ToDo项就花费了很多时间。 在Vue中,我能够简单地编写:

<input type=”text” v-on:keyup.enter=”createNewToDoItem”/>

我们如何将数据传递给子组件? (How do we pass data through to a child component?)

React: (React:)

In react, we pass props onto the child component at the point where it is created. Such as:

在react中,我们将道具传递到子组件的创建位置。 如:

<ToDoItem key={item.id} item={item} deleteItem={deleteItem} />;

Here we see two props passed to the ToDoItem component. From this point on, we can now reference them in the child component via this.props. So to access the item.todo prop, we simply call props.item. You may have noticed that there's also a key prop (so technically we're actually passing three props). This is mainly for React's internals, as it makes things easier when it comes to making updates and tracking changes among multiple versions of the same component (which we have here because each todo is a copy of the ToDoItem component). It's also important to ensure your components have unique keys, otherwise React will warn you about it in the console.

在这里,我们看到两个传递给ToDoItem组件的道具。 从现在开始,我们现在可以通过this.props在子组件中引用它们。 因此,要访问item.todo prop,我们只需调用props.item 。 您可能已经注意到,还有一个key道具(因此从技术上讲,我们实际上正在传递三个道具)。 这主要用于React的内部,因为它使在同一组件的多个版本之间进行更新和跟踪更改变得容易(我们在这里拥有它,因为每个todoToDoItem组件的一个副本)。 确保您的组件具有唯一键也很重要,否则React会在控制台中警告您。

Vue: (Vue:)

In Vue, we pass props onto the child component at the point where it is created. Such as:

在Vue中,我们将道具传递到子组件的创建位置。 如:

<ToDoItem v-for="item in list" :item="item" @delete="onDeleteItem" :key="item.id" />

Once this is done, we then pass them into the props array in the child component, as such: props: [ "todo" ]. These can then be referenced in the child by their name — so in our case, todo. If you're unsure about where to place that prop key, here is what the entire export default object looks like in our child component:

完成此操作后,我们将它们传递到子组件的props数组中,如下所示: props: [ "todo" ] 。 然后可以在孩子的名字中引用它们的名称,因此在我们的情况下为todo 。 如果您不确定该prop键的放置位置,则这是整个export default对象在子组件中的外观:

export default {
name: "ToDoItem",
props: ["item"],
setup(props, { emit }) {
function deleteItem(id) {
emit("delete", id);
}
return {
deleteItem,
};
},
};

One thing you may have noticed is that when looping through data in Vue, we actually just looped through list rather than list.value. Trying to loop through list.value won't work here

您可能已经注意到的一件事是,当在Vue中遍历数据时,实际上我们只是遍历了 list 而不是 list.value 尝试遍历 list.value 在这里行不通

我们如何将数据发回到父组件? (How do we emit data back to a parent component?)

React: (React:)

We firstly pass the function down to the child component by referencing it as a prop in the place where we call the child component. We then add the call to function on the child by whatever means, such as an onClick, by referencing props.whateverTheFunctionIsCalled — or whateverTheFunctionIsCalled if we have used destructuring. This will then trigger the function that sits in the parent component. We can see an example of this entire process in the section ‘How do we delete from the list’.

首先,通过在调用子组件的地方将其作为道具引用,将函数传递给子组件。 然后,我们用任何手段,如一个onClick调用添加到功能上的孩子,通过引用props.whateverTheFunctionIsCalled -或者,如果我们用解构whateverTheFunctionIsCalled。 然后,这将触发位于父组件中的函数。 我们可以在“如何从列表中删除 ”部分中看到整个过程的示例

Vue: (Vue:)

In our child component, we simply write a function that emits a value back to the parent function. In our parent component, we write a function that listens for when that value is emitted, which can then trigger a function call. We can see an example of this entire process in the section ‘How do we delete from the list’.

在子组件中,我们只编写了一个将值返回给父函数的函数。 在父组件中,我们编写了一个函数,该函数侦听何时发出该值,然后可以触发函数调用。 我们可以在“如何从列表中删除 ”部分中看到整个过程的示例

我们终于得到它了! 🎉 (And there we have it! 🎉)

We’ve looked at how we add, remove and change data, pass data in the form of props from parent to child, and send data from the child to the parent in the form of event listeners. There are, of course, lots of other little differences and quirks between React and Vue, but hopefully the contents of this article has helped to serve as a bit of a foundation for understanding how both frameworks handle stuff.

我们已经研究了如何添加,删除和更改数据,如何以props形式将数据从父级传递到子级,以及如何以事件侦听器的形式将数据从子级发送到父级。 当然,React和Vue之间还有许多其他的小差异和怪异之处,但是希望本文的内容有助于为理解这两个框架如何处理事物奠定基础。

If you’re interested in forking the styles used in this article and want to make your own equivalent piece, please feel free to do so! 👍

如果您有兴趣分叉本文中使用的样式,并想制作自己的同等作品,请随时这样做! 👍

Github链接到两个应用程序: (Github links to both apps:)

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

Vue待办事项: https//github.com/sunil-sandhu/vue-todo-2020

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

React待办事项: https : //github.com/sunil-sandhu/react-todo-2020

本文的2019年版本 (The 2019 version of this article)

https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-2019-edition-42ba2cab9e56

https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-2019-edition-42ba2cab9e56

本文的2018年版本 (The 2018 version of this article)

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

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

If you would like to translate this article into another language, please go ahead and do so — let me know when it is complete so that I can add it to the list of translations above.

如果您想将本文翻译成另一种语言,请继续进行-完成后请告诉我,以便将其添加到上面的翻译列表中。

普通英语JavaScript (JavaScript In Plain English)

Enjoyed this article? If so, get more similar content by subscribing to Decoded, our YouTube channel!

喜欢这篇文章吗? 如果是这样,请订阅我们的YouTube频道解码,以获得更多类似的内容

Originally posted at: sunilsandhu.com

最初发布于: sunilsandhu.com

翻译自: https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-2020-edition-36657f5aafdc

vue和react相同点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值