If you seek job opportunities, you will see three frontend frameworks dominate the frontend world.
- React
- Angular
- Vue
React
React is the most used frontend library in frontend development. Based on my experience, once you know the principles of React, it is easy to use. Unlike the other frameworks, you may feel you're dealing with Javascript more than HTML. You also may find things strange like the rendering process and a property name className
.
Angular
Since I haven't had experience working with Angular, I don't have any strong opinions about it. However, from what I have heard about Angular from youtube videos and articles I read, Angular is quite a big framework and has almost everything we need to develop a frontend project. I wouldn't mind working with Angular if I have to, but, frequent version changes and coming with many features don't sound intriguing to me. Even though, I admit that there's a lot to learn from its structures as a frontend developer.
Vue
According to 2023 StateOfJS Survey), Vue is the second most used frontend framework. It has surpassed Angular last year. Easy to use and high performance first come to my mind when I think of Vue.
During the time applying for jobs for the last couple of months, I thought it would be good to know a little bit about Vue to expand job opportunities. Last year, when I tried SolidJS one time. I learned a lot and also, I got to get a better understanding of React.
I will compare things that I found different between Vue and React while building a todo app using Vue. I spent only some hours on it, therefore, something might not sound right. If you find anything that doesn't sound right, please let me know in the comment below. Thank you very much.
App Preview
This is the todo app.
I created components using Single File Component, and I utilized json-server for implementing an API server.
Comparison
Properties
React
import React from 'react';
function TodoItem({ title, desc, done }: { title: string, desc:string, done: boolean }) {
return (
<>
<h2>{title}</h2>
<p>{desc}</p>
<span>{done ? 'checked' : 'unchecked'}</span>
</>
)
}
export default function App() {
return <TodoItem title="title" desc="desc" done={true} />;
}
Vue
// App
<script setup>
import TodoItem from './TodoItem.vue'
</script>
<template>
<TodoItem title="title" desc="desc" :done="true" />
</template>
// TodoItem
<script setup lang="ts">
const props = defineProps<{
title: string
desc: string
done: boolean
}>()
</script>
<template>
<h2>{{ props.title }}</h2>
<p>{{ props.desc }}</p>
<span>{{ props.done ? 'checked' : 'unchecked' }}</span>
</template>
While React components get properties from the parameters, in Vue3, components receive properties from the defineProps
function in non-setup script
components.
You can define type definition for properties using generic type arguments like in React, but Vue 3 also provides an additional way to define prop types, the runtime props option.
Passing properties to the component is the same in both React and Vue. They are passed as attributes with the properties' names and the values.
There is a difference when you want to pass variables in javascript.
In React, you can inject javascript code within curly brackets {}
. In Vue, you use v-bind
. Here, in the example,:
is used, which is a shorthand of v-bind
.
I'm not used to Vue yet though, for me, The way React uses makes more sense, curly brackets to inject js code.
Children
React
import React from 'react';
function Child({ children }: { children: React.ReactNode }) {
return (
<>
{children}
</>
)
}
export default function App() {
return (
<Child>
<h1>Child Component</h1>
</Child>
);
}
Vue
// App
<script setup>
import Child from './Child.vue'
</script>
<template>
<Child>
<h1>Child Component</h1>
</Child>
</template>
// Child
<template>
<slot />
</template>
To pass the HTML code written in the component, React uses the prop, children
while Vue uses the slot
tag. In Vue, it is more convenient as you don't need to mention to use it.
Custom Events
React
import React from 'react';
function Child({ onClick }: { onClick: (msg: string) => void }) {
return (
<div onClick={() => onClick("message")}>Child</div>
)
}
export default function App() {
return <Child onClick={(msg) => console.log(msg)} />;
}
Vue
// App
<script setup>
import Child from './Child.vue'
</script>
<template>
<Child @click="(msg) => console.log(msg)" />
</template>
// Child
<script setup lang="ts">
const emit = defineEmits<{
(e: 'click', msg: string): void
}>()
</script>
<template>
<div @click="emit('click', 'message')">Child</div>
</template>
In React, custom events are delivered via props, so defining the type of custom events is the same as the other props.
In Vue, you use the built-in $emit
method to implement custom events. However, to explicitly declare the events, you use the defineEmits
function.
I like the idea of separating events from properties. The way I see it, It seems clearer than mixing up all the properties in one place. However, In my opinion, Passing altogether is simpler than separating them.
By the way, @
is a shorthand of v-on
.
Data Binding
React
import React, { useState } from 'react';
export default function App() {
const [text, setText] = useState('');
return (
<>
<input value={text} onChange={e => setText(e.target.value)} />
<h1>{text}</h1>
</>
);
}
Vue
<script setup lang="ts">
import { ref } from 'vue'
const text = ref('')
</script>
<template>
<input v-model="text" />
<h1>{{ text }}</h1>
</template>
As React doesn't provide a data-binding feature, we must pass handlers to update states. On the other hand, Vue provides a data-binding. So, we don't need to implement the logic by ourselves to update states.
However, when we work on a React project, we likely use form libraries to handle form inputs like react-hook-form, and it also provides various features to manage form inputs efficiently such as error handling, validation, and so on.
Directives
React
{
todos.map((todo) => (
<Todo
key={todo.id}
title={todo.title}
desc={todo.desc}
done={todo.done}
onDone={handleDone(todo.id)}
onEdit={handleEdit(todo.id)}
onDelete={handleDelete(todo.id)}
/>
))
}
{
todos ?
<TodoList
todos="todos"
/> :
<i v-else class="pi pi-spinner loading"></i>
}
Vue
<Todo
v-for="todo in props.todos"
:key="todo.id"
:title="todo.title"
:desc="todo.desc"
:done="todo.done"
@done="emit('done', todo.id)"
@edit="emit('edit', todo.id)"
@delete="emit('delete', todo.id)"
/>
<TodoList
v-if="todos"
:todos="todos"
/>
<i v-else class="pi pi-spinner loading"></i>
SolidJS also provides control-flow components such as For
and Show
that I found it would be good to have in React. Although that stuff can be componentized the same way in React, since it's not standard, many use javascript like map
and ternary operator
.
In Vue, there are directives like v-for
, v-if
, and v-show
. As they' are provided by the frontend framework, you don't need to worry about anything else besides knowing how to use them from the docs. For instance, In React, to implement conditional rendering, you might have to choose among options, for, if, switch, and ternary operator. I think this is pretty cool, those are provided at the framework level.
Update States
To reflect data changes onto the screen, Vue uses Proxy API, by using it, it knows exactly where it needs to be updated.
In React, to update states, you use setState and it causes re-render.
Conclusion
Working with Vue feels like I work in HTML in template engines. As It provides a variety of directives, I didn't write any JS such as for list rendering and conditional rendering. Proxy API was also an interesting part. Experience with SolidJS got me a quick understanding of it. As a frontend developer who has mostly been working with React, this is kind of a new world. Thinking of it, updates places where need to be updated sounds obviously better than executeing a whole component function. This is why many React projects leak performance. However, React has solutions useCallback
, useMemo
, memo
and stuff like that to prevent this and React compiler is in an experimental stage now. React has its own principles. While I admit amazing features I could use in Vue out of the box, I like React's simplicity, or maybe I just got used to it.
Knowing how each library/framework works widened my eyes. If you have experience with only one framework, I strongly recommend trying other frontend libraries/frameworks. It may be helpful to get an understanding of the frontend library/framework better that you're actively using.
THanks a lot, you can see the full code https://github.com/hsk-kr/vue-todo.
Happy Coding!
Top comments (0)