zishu's blog

zishu's blog

一个热爱生活的博主。https://zishu.me

How big is the difference between creating the same app with React and Vue?

In comparing the React framework and the Vue framework, I will write the same program in both and examine the differences in their code implementations. How significant are these differences?

Reprinted from: https://blog.csdn.net/csdnnews/article/details/81880378
Original article: https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-e9a1ae8077fd
Author: Sunil Sandhu, a web full-stack engineer + dreamer.
Translator: An Xiang, editor: Tu Min

As we all know, Vue and React are currently very famous front-end frameworks. I often use Vue in my work, so I have a deep understanding of it. At the same time, I am also curious about React and want to learn more about it.

So, I read the React documentation and watched some video tutorials. Although these resources are great, what I really want to understand is the differences between React and Vue. By "differences," I don't mean whether they both have virtual DOMs or how they render pages, but rather I hope someone can explain the differences between the two from a coding perspective. I wanted to find an article that explains these differences so that beginners in Vue or React can better understand them.

Unfortunately, I did not find such an article. So, I realized I had to compare Vue and React myself. During my self-study process, I documented the specific process in this article.

1. Objective#

I will build a standard to-do list application that allows users to add and delete items from the list. Both applications will be built using the default CLI (command-line interface), with React using create-react-app and Vue using vue-cli.

The appearance of both applications is as follows:

image

The CSS code for both applications is almost identical, but the locations of these codes differ. With that in mind, let's take a look at the file structure of both applications:

image

You will find that their structures are almost identical. The only difference is that the React App has three CSS files, while the Vue App has no CSS files. This is because the create-react-app component requires an accompanying file to save its styles, while Vue CLI adopts a full-package approach, declaring its styles within the actual component files.

The results of these two different strategies are the same, and developers will soon be able to master both strategies. Developers can choose based on their preferences, and you will hear a lot of discussions in the development community about how to build CSS. Above, we have listed the code structure following both CLIs.

Before we discuss further, let's quickly look at what a typical Vue and React component looks like:

image

Now let's officially start and delve into the details!

2. How to Modify Data#

First, we need to understand what "modifying data" means. It sounds a bit academic, but it's actually quite simple: it's about changing the data we have already stored. For example, if we want to change a person's name variable from "Jhon" to "Mark," we need to perform the "modify data" operation. At this point, React and Vue handle this differently. Vue essentially creates a data object whose data can be freely changed; React creates a state object, and changing data requires some additional operations. React needs these extra operations for its own reasons, which I will explain in detail later. Before that, let's take a look at the data object in Vue and the state object in React:

Vue Data Object
image

React State Object
image

From the images, we can see that we are passing in the same data, but their marking methods are different. Therefore, the way initial data is passed to the component is very similar. However, as we mentioned, the way data is changed in the two frameworks is different.

Assuming we have a data element named name: ‘Sunil’.

In Vue, we reference it by calling this.name. We can also update it by calling this.name ='John'. This way, the name is successfully changed to "Jhon".

In React, we reference the same piece of data by calling this.state.name. Now, the key difference is that we cannot simply write this.state.name ='John', because React has a restriction mechanism that prevents this simple modification. In React, we need to write: this.setState({name: 'John'}).

While this essentially achieves the same result as we implemented in Vue, the operation in React is more cumbersome because Vue combines its own setState version by default every time data is updated. In simple terms, React requires setState to update its internal data, while for Vue, when you update the value of the data object, it defaults to your intent to change. So why doesn't React simplify this? Why is setState necessary? Revanth Kumar explains:

"This is because React wants to rerun certain lifecycle hooks when the state changes, such as componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate, render, componentDidUpdate. When you call the setState function, it knows the state has changed. If you directly change the state, React will have to do more work to track the changes and run lifecycle hooks, etc. So for simplicity, React uses setState."

image

3. Adding New To-Do Items#

React Implementation#

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

In React, our input field has a property called value. This value is automatically updated using several functions that are bound together to create two-way binding. We create this form of two-way binding by attaching an onChange event listener to the input field. Let's take a look at the code:

<input type="text" 
       value={this.state.todo} 
       onChange={this.handleInput}/>

Whenever the value of the input field changes, the handleInput function runs. It updates the state object’s todo with whatever is in the input field. The handleInput function is as follows:

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

Now, whenever the user presses the + button on the page to add a new item, the createNewToDoItem function runs this.setState and passes a function to it. This function has two parameters: the entire list array from the state object and the todo updated by the handleInput function. Then the function returns a new object that contains the entire previous list and adds todo to its end. The entire list is added using the spread operator.

Finally, we set todo to an empty string, which automatically updates the value in the input field.

Vue Implementation#

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

In Vue, our input field has a handle called v-model. This implements **two-way binding. The input field code is as follows:

<input type="text" v-model="todo"/>

V-Model binds the content of the input field to a key in the data object called toDoItem. When the page loads, we set toDoItem to an empty string, for example: todo: ' '. If there is already data, such as todo: 'Add text here', the input field will load the input content of "Add text here". In any case, setting it as an empty string means that any text we type in the input field will bind to todo. This is essentially two-way binding (the input field can update the data object, and the data object can update the input field).

So, looking back at the previous createNewToDoItem() code block, we store the content of todo in the list array and then set todo to an empty string.

4. Deleting To-Do Items#

React Implementation#

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

Although the deleteItem function is located in the ToDo.js file, it is also easy to reference it from the ToDoItem.js file by passing the deleteItem() function as a prop:

<ToDoItem deleteItem={this.deleteItem.bind(this, key)}/>

This passes the function to the child component, allowing it to access it. We bind this and pass the key parameter, so when the user clicks to delete an item, the function distinguishes which ToDoItem the user clicked on by the key. Then, inside the ToDoItem component, we do the following:

<div className="ToDoItem-Delete" onClick={this.props.deleteItem}>-</div> 

To reference a function located in the parent component, simply reference this.props.deleteItem.

Vue Implementation#

onDeleteItem(todo){
  this.list = this.list.filter(item => item !== todo);
}

The Vue implementation is slightly different; we need to do the following three things:

  1. First, call the function on the element:
<div class="ToDoItem-Delete" @click="deleteItem(todo)">-</div>
  1. Then we must create an emit function as an internal method of the child component (in this case, ToDoItem.vue), as follows:
deleteItem(todo) {
    this.$emit('delete', todo)
}
  1. After that, you will find that when we add ToDo.vue's ToDoItem.vue, we are actually referencing a function:
<ToDoItem v-for="todo in list" 
    :todo="todo" 
    @delete="onDeleteItem" // <-- this :)
    :key="todo.id" />

This is called a custom event listener. It listens for any triggered events using the string 'delete'. Once the event is detected, it triggers a function called onDeleteItem. This function is located inside ToDo.vue, not ToDoItem.vue. As mentioned earlier, this function simply filters the todo array within the data object to remove the clicked to-do item.

It is also worth noting in the Vue example that we can write the $emit part in the @click listener, making it simpler, as follows:

<div class="ToDoItem-Delete" @click="$emit('delete', todo)">-</div> 

If you prefer, this can reduce the three steps to two.

In React, child components can access parent functions via this.props, while in Vue, you need to emit events from the child component for the parent to collect them.

5. How to Pass Event Listeners#

React Implementation#

Handling event listeners for simple events (like clicks) is very straightforward. We created a click event for the to-do items to create new to-do items, as shown in the code:

<div className="ToDo-Add" onClick={this.createNewToDoItem}>+</div>

Very simple, just like handling inline onClick with vanilla JS. As mentioned earlier, setting up event listeners when pressing the enter key takes longer. This requires handling the onKeyPress event for the input tag, as shown in the code:

<input type="text" onKeyPress={this.handleKeyPress}/>

This function will trigger the createNewToDoItem function as soon as it detects that the 'enter' key has been pressed, as shown in the following code:

handleKeyPress = (e) => {
  if (e.key === 'Enter') {
    this.createNewToDoItem();
  }
};

Vue Implementation#

Vue's event listeners are more straightforward. We just need to use a simple @ symbol to build the event listeners we want. For example, to add a click event listener, the code is:

<div class="ToDo-Add" @click="createNewToDoItem()">+</div> 

Note: @click is actually a shorthand for v-on. Vue event listeners are powerful; you can choose properties for them, such as .once to prevent the event listener from being triggered multiple times. Additionally, it includes many shortcuts. When pressing the enter key, React takes longer to create the event listener to create new ToDo items. In Vue, the code is as follows:

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

6. How to Pass Data to Child Components#

React Implementation#

In React, we pass props to the child component at the time of creation. For example:

<ToDoItem key={key} item={todo} />

Here we pass two props to the ToDoItem component. Then, we can reference them in the child component via this.props. Therefore, to access the item.todo prop, we simply call this.props.item.

Vue Implementation#

In Vue, we pass props to the child component at the time of creation as follows:

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

We pass them to the props array in the child component, such as: props: ['id', 'todo']. Then they can be referenced by name in the child component.

7. How to Send Data Back to Parent Components#

React Implementation#

We first pass a function to the child component by referencing it as a prop when we call the child component. Then we add the function call to the child component by referencing this.props.whateverTheFunctionIsCalled, for example, onClick. This will trigger the function in the parent component. The entire process is detailed in the section on deleting to-do items.

Vue Implementation#

In the child component, we simply write a function to send a value back to the parent function. In the parent component, we write a function to listen for when the child component emits that value's event, triggering the function call once the event is detected. Again, the entire process is detailed in the section on deleting to-do items.

8. Conclusion#

We have explored adding, deleting, and changing data, passing data from parent components to child components as props, and sending data from child components back to parent components in the form of event listeners. Of course, there are some minor differences between React and Vue, and I hope the content of this article helps to understand these two frameworks better.

The GitHub addresses for both applications are:

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

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

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.