Make Your Web App Reactive With Vue Reactivity
Join the DZone community and get the full member experience.
Join For FreeIntroduction
During recent years, I've been working more and more with Vue.js. It's a pleasure to work with it, compared to other frameworks. To be clear, it is a large and feature rich framework as well, but somehow it feels much lighter and easier to digest (pun intended ;-) than its rivals.
While studying the upcoming Vue.js v3 release, I have noticed that it has become highly modular. Particularly, the most essential feature of Vue.js, which is its reactivity system, is now available as a standalone module. Turns out that to use it, one actually does not need all of Vue.js!
Vue.js Reactivity in a Pill
In essence, Vue.js reactivity allows individuals to run code automatically in response to mutations of data. How is it useful? Well, it's running every Vue component. Take this barebones Vue component, where the click of a button changes the welcome message:
x
<template>
<div>
<button @click="this.message='Welcome, traveller!'">
Click me
</button>
<label>
{{ message }}
</label>
</div>
</template>
Its Vue reactivity system that detects that message data property has changed when I clicked the button. It will render the label accordingly.
Notice that Vue's reactivity system does not care about mouse clicks. It could be any other event — a timer or an asynchronous web call. It reacts because a reactive message property has changed, whatever the reason. In response to that change, it will render a <label> element because it depends on the message property. If there were any other elements referring to message, they would all be rendered as well.
It Works Outside Vue Components Just as Well
It turns out that with Vue.js 3, reactivity can be used outside Vue components. Here's a simple example:
x
<html>
<head>
<meta charset="utf-8">
<title>Vue Reactivity Without Vue</title>
<script src="https://cdn.jsdelivr.net/npm/@vue/reactivity@3.0.0-beta.15/dist/reactivity.global.min.js"></script>
<script type="module" src="index.js"></script>
</head>
<body>
<button id="btn">Click me</button>
<div id="counter">0 clicks</div>
</body>
</html>
and the accompanying script:
x
const { reactive, computed, effect } = window.VueReactivity
const state = reactive({
counter: 0,
label: computed(() =>
`${state.counter} click${state.counter === 1 ? '' : 's'}`)
})
effect(() => {
const counter = document.querySelector('#counter')
counter.innerHTML = state.label
})
window.addEventListener('load', () => {
const button = document.querySelector('#btn')
button.addEventListener('click', () => {
state.counter++
})
})
It runs without babel, webpack, TypeScript, CLI tools, without anything we take for granted as a necessary evil these days. All it needs to run is a decent browser.
In the example, we have a label displaying a number of clicks of a button.
We've introduced a simple state object containing a counter. The state is made reactive with the helper function from Vue Reactivity module.
State also has a computed property that returns a human-friendly label. Just to remind, unlike object getters which are evaluated each time they're called, a computed property is smarter — it's evaluated only when values it uses are changed.
Whenever the button is clicked, counter in the state is increased and label is updated. This is all done by Vue reactivity. The code which assigns new HTML content to the #counter element is wrapped in an effect()
wrapper. This tells the reactivity system to observe if any of the reactive objects used in this code have changed.
When I click a button, state.counter
is increased. Because state.counter
is reactive, Vue reactivity system calls all effects that depend on it. This means that our #counter element will be refreshed immediately.
Why Would I Want to Use It?
The main reason for introducing frameworks like Vue, React, or Angular is their support for state management and automatic synchronization of that state with UI representing it.
In some cases, that's just too much. Introducing a framework comes with a price — a complex build pipeline, CLI tools, plenty of assumptions, and conventions and requirements to follow. In many simple scenarios, one just does not need all that. But one still needs simple state management, and would benefit from declarative way of defining the UI and automatic propagation of state changes to UI.
This all can be done with the minimalistic Vue.js reactivity system. The library itself is a mere 4.5kB, so it doesn't add any significant burden. Yet, it allows you to build small web pages and mini-applications using the same paradigms as their bigger peers:
- Application state, clearly defined and separated from UI.
- Declarative UI where we can specify recipes to render elements using application state, and that's all we care about.
Reactivity system takes care of watching changes in state and re-rendering my UI elements whenever necessary. I no longer have to call code updating all the bits and pieces in the UI. I no longer worry whether I called them in a right order or whether I have forgotten about some of them, leaving my UI in an inconsistent state.
All in all, it helps us create even the smallest web applications in a safe and robust way, having the same quality and stability as large web applications using big frameworks.
References
JSFiddle with the example code can be seen here: https://jsfiddle.net/letsdebugit/ybtrwLn2/4/
You can learn more about how Vue.js reactivity works in the following in-depth articles:
https://vuejs.org/v2/guide/reactivity.html
https://vuejsdevelopers.com/2017/03/05/vue-js-reactivity/
The latest version of @vue/reactivity library can be found at https://www.builtforvue.com/@vue/reactivity and https://github.com/vuejs/vue-next/tree/master/packages/reactivity
All credits go to Vue.js creators, thank you for your awesome work!
Opinions expressed by DZone contributors are their own.
Trending
-
Playwright JavaScript Tutorial: A Complete Guide
-
The SPACE Framework for Developer Productivity
-
Auditing Tools for Kubernetes
-
Redefining DevOps: The Transformative Power of Containerization
Comments