A matter of preference
Introduction
Time and time again, I log into Twitter and encounter the same discussion: React is better; Vue is better; have you heard of Svelte? I'm also told Angular is still a thing. However, if you closely examine the language features of each, there are minimal differences beyond the application of said features. For this article I will mainly concentrate on React and Vue as those are the two technologies in which I have the most experience
Virtual DOM
One of the most significant common traits is the use of Virtual DOM. The Virtual DOM is an abstraction of the HTML DOM where every HTML element is a JavaScript object. This approach offers some performance gain and enables DOM manipulation in a more declarative fashion.
Lifecycle methods
Both of the libraries allow us to hook into component lifecycle stages through a number of methods. In React, we are given the following methods:
componentDidMount
for initial mounting,componentDidUpdate
for when props/DOM updatescomponentWillUnmount
for when the component will disappear.
It is slightly different if you are writing functional React components; instead of using lifecycle methods, you can use a useEffect
hook to emulate this behavior. This is also a cleaner approach to take when trying to emulate the componentDidUpdate
method, as you can specify which exact props/elements you want to trigger an update.
With useEffect
, if we create an instance of this method with an empty dependencies array, then it will run once on the component's mounting and also run once when the component will unmount through a returned closure function:
useEffect(() => { console.log("I'm mounted") return () => console.log("I'm unmounting") }, [])
When we provide useEffect
with a dependencies array, it will update when those dependencies update:
useEffect(() => { console.log("test prop has changed") }, [testProp])
In Vue, we have similar methods, but quite a lot more of them:
beforeCreate
, this is the first hook to be called after the Vue instance is created;created
, which is called next and gives us our first access to props, computed properties, etc.;beforeMount
, which is called before Vue is mounted on the DOM (no DOM manipulation can be done here);mounted
, when this is called the component is functional and ready to go;beforeUpdate
, which is called anytime there is an update to the data that requires the DOM to be updated;updated
, which is called just after the DOM update has occurred; -beforeDestroy
, which is called just before the Vue instance is destroyed (mainly to be used for resource management);destroyed
, which is the final hook called when the component/Vue instance is finally destroyed. All listeners, directives, and events are unbound here.
Props
If we compare Vue and React in terms of how Props are passed, the main difference is in the syntax. In Vue, Props can be declared before-hand using the "props" option, for example:
<template> {{title}} </template> export default { props: { title: String }, }
In React, props can be accessed differently depending on the type of component. For functional components, props are passed as an argument to the function. For class-based components, props are accessed using the keyword this
.
const MyComponent = ({ title }) => <h1>{title}</h1>; class MyComponent () { render() { return <h1>{this.props.title}</h1> } }
When passing props in Vue, the convention is to use camelCase when declaring prop names in the component definition and kebab-case when using the props in the HTML template. This aligns with the HTML attribute convention and makes it easier to work with props. The Vue compiler will automatically transform kebab-case props to camelCase in the component definition, so you don't have to worry about quotations or any other syntax. It's important to note that this convention is only strictly enforced in Vue DOM Templates. For more information, please refer to the Vue documentation here.
<template> <MyComponent blog-title="blog title" /> </template> // in the my component file export default { props: { title: String }, }
Conclusions
This article has only highlighted a few similarities between the two libraries, however, the decision of which library to use ultimately comes down to personal preference. Even though they share certain features, the two libraries have distinct approaches. Ultimately, it is up to you to decide which library best suits your needs.