Why I use Vue
I have used Vue as my main framework since 2019. While Vue is one of the “big three” by adoption, just alongside React and Angular, people are still usually surprised when I tell them. In this post I will explain the reasons behind my choice.
To put it shortly, I like Vue because it has an emphasis on DX, doesn’t overcomplicate things and has everything you need included (and yes, it is still very fast)!
Let’s see some examples:
You write js in <script>, css in <style> and html in <template>
Vue components are written as Single File Components. You write CSS in <style>, html with template engine in <template> and javascript in <script>. It feels like writing a simple html file — a cornerstone of the web. Almost anyone in your team will understand how to make edits in such files.
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<button @click="count++">Count: {{ count }}</button>
</template>
<style scoped>
button {
color: blue;
}
</style>
Non JSX templates
Templates are written as html with attributes like v-for, v-if, v-else. You don’t mix JS with HTML, and as a result get more readable code than JSX (ask non-js people!).
<template>
<div v-if="user">
<h1>Hello, {{ user.name }}!</h1>
<ul>
<li v-for="item in items" :key="item.id">
{{ item.title }}
</li>
</ul>
</div>
<p v-else>Please log in</p>
</template>
You write CSS as CSS
You can write regular CSS and just add scoped attribute to <style> to encapsulate it. No need for CSS modules, CSS-in-JS and other stuff. Just write CSS and everything works.
<style scoped>
.card {
padding: 1rem;
border-radius: 8px;
}
/* Won't affect other components */
</style>
Reactivity tools are reasonably named and framework has performance optimizations built-in
So you mark values as reactive with ref, compute values with computed and watch values with watch. Usually you don’t need to think about optimizing these.
// `ref` is the way to mark value as reactive, like useState
const count = ref(0);
// `computed` is value that was computed. It won't be recomputed if all dependent values are the same. Same as useMemo in react
const doubled = computed(() => count.value * 2);
// `watch` watches value, just like useEffect in react
watch(count, (newValue) => {
console.log(`Count changed to ${newValue}`);
});
Components communicate via events
Components communicate with each other via events that go up. This results in much cleaner code without a need for callback prop drilling / overreliance on stores or resolving shadowing issues.
<!-- Child.vue -->
<button @click="$emit('update', newValue)">Update</button>
<!-- Parent.vue -->
<Child @update="handleUpdate" />
Vue ecosystem is great
For most cases you can find exactly one great solution made by someone close to the Vue or Nuxt teams. A few examples:
- You may know
viteandvitestthat started as part of the Vue ecosystem, and now they are integral (and the least annoying) parts of the frontend toolchain. - In Vue’s default state manager pinia you can update state like
store.count++. In redux you would need to have at least a PhD in computer science to do that.
Attributes passed to component
Anything that is not a declared prop is passed to the component as an attribute. The same works for classes, which will be joined in the expected way. Why this is not the default behaviour in other frameworks is a mystery to me.
<!-- MyButton.vue - only declares 'label' prop -->
<template>
<button class="btn">{{ label }}</button>
</template>
<!-- Using the component -->
<MyButton label="Click" class="primary large" data-test="btn" />
<!-- Renders: <button class="btn primary large" data-test="btn">Click</button> -->
<!-- Classes are automatically joined! -->
To sum up
I think even with its high adoption Vue is still a very undervalued framework.
- It has great DX and it’s accessible for programmers of all backgrounds
- It has great performance, without a need to constantly optimize it
- It’s widely adopted so even quite a big company can find enough people who have hands-on experience with Vue
So, don’t be afraid to try Vue!