This content originally appeared on DEV Community and was authored by Jordan Brennan
There’s some simple patterns I tend to follow in my Vue projects that I figure work well enough to share, so here ya go.
I’m really curious to see what other people do for these cases, so please share.
Loading state
I use a simple loading
object of true/false flags that I toggle whenever that loading state changes. Messaging, loading indicators, and entire content sections are driven by these flags.
Even though there are cases where I could use the presence or absence of the relevant data, using a separate object provides the flexibility needed for any design requirement.
An example:
<template>
<div>
<div v-if="loading.users">Loading users</div>
<table v-if="!loading.users">
...
</table>
</div>
</template>
<script>
export default {
data() {
return {
users: [],
loading: {users: false}
}
},
created() {
this.loading.users = true;
fetch('/users')
.then(users => this.users = users)
.catch(console.error)
.finally(() => this.loading.users = false)
}
}
</script>
Error messaging
Similar to loading states, I set up a simple errors
object and toggle flags. I’ve found error messages are best done in the template rather than in the errors object because one error can sometimes trigger multiple UI bits.
An example:
<template>
<div>
<div v-if="errors.fetchUsers">Failed to load users.</div>
</div>
</template>
<script>
export default {
data() {
return {
users: [],
errors: {fetchUsers: false}
}
},
created() {
fetch('/users')
.then(users => this.users = users)
.catch(err => {
this.errors.fetchUsers = true;
console.error(err);
})
}
}
</script>
Occasionally a component needs to know if there are any errors at all. That's really easy to check for:
// Basic programmatic check
const hasErrors = Object.values(this.errors).some(err => err)
// Or as a computed
computed: {
hasErrors: function () {
return Object.values(this.errors).some(err => err)
}
}
Avoid Event Modifiers
From the docs:
<form v-on:submit.prevent="onSubmit"></form>
That .prevent
is a shortcut to the already short e.preventDefault()
. The cost of proprietary markup like this scattered all over your app trumps their negligible convenience.
A strength Vue (and Riot) have is their plainness. That makes them easier to adopt and easier to replace. Using too much of a framework's special sauce increases the dependency - not good! And makes it harder for newcomers to understand your code as well.
Flatter component hierarchy
I avoid nesting Vue components beyond the third layer. The fourth layer is implemented as Custom Elements because I strongly prefer to write vanilla js any time there isn't a need for framework-specific features.
My Vue (and Riot) projects look like this:
This is an ideal design I could never quite achieve with React because React struggles a bit with Custom Elements even though they are a web standard.
Shared modules
This one may be obvious, but I sometimes see over-engineered solutions for these kinds of problems so I figured it's worth sharing.
Instead of creating a Vue component or custom directive or other Vue-dependent solution, I strive to use simple Vue-free modules where possible. For example, in several components I need to format a raw number of bytes as KB, MB, GB, etc. I export a function that does this and import it in the components that need it:
// data-utils.js
// No Vue allowed!
export function formatBytes(bytes = 0) {
// Zero is a valid value
if (bytes <= 0) return '0 bytes';
// Handle non-zero falsy
if (!bytes) return '';
// Format value, e.g. "5 MB"
const k = 1024;
const sizes = ['bytes', 'KB', 'MB', 'GB', 'TB'];
const size = Math.floor(Math.log(bytes) / Math.log(k));
const num = parseFloat((bytes / Math.pow(k, size)).toFixed(2))
return `${num} ${sizes[size]}`;
}
<template>
<div>
<p>File size is {{ formatBytes(file.size) }}</p>
</div>
</template>
<script>
import {formatBytes} from '../data-utils';
export default {
data() {
return {
file: new File()
}
},
methods: {
formatBytes
}
}
</script>
I usually end up with a dozen or more of these and they're so much easier to write, use, and test when there's no dependency on Vue itself even though they're for a Vue project. Sometimes these end up graduating to a shared package that can be used by other projects because they're decoupled from Vue.
Beyond that I'm just using the basic features of Vue as-is and that alone takes me incredibly far. It's this straight-forwardness that makes Vue more powerful than other more ambitious and proprietary frameworks. Vue gives you so much more than it takes in my experience, and in many cases you don't have to let it take either.
Beyond the basics, what patterns are you using in Vue?
This content originally appeared on DEV Community and was authored by Jordan Brennan

Jordan Brennan | Sciencx (2021-07-30T19:43:55+00:00) Helpful patterns I use in Vue. Retrieved from https://www.scien.cx/2021/07/30/helpful-patterns-i-use-in-vue/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.