Using Vue's class function in your own composables

Inside your <template>, you may be used to stacking lots of conditionally applied classes onto elements. You can add dynamic classes (e.g. .btn--${props.type}), arrays of conditional if/else classes (e.g. props.error ? 'has-error' : 'is-valid') or even whole objects of conditionals (e.g. { 'is-disabled': props.disabled }. But what do we do if we want to shift that logic to our <script> block?

While undocumented (and thus not a guaranteed API, so tread carefully), Vue internally uses a pretty simple function to make all this magic happen, and you can import it too.

import { normalizeClass } from "vue";

There it is. There’s the magic.

Combine this with a computed getter and you’ve got a reactive class string with support for static, dynamic, array and object classes.

Here’s an example for you to finish with:

1<template>
2 <button :class="buttonClass" @mouseenter="hover = true" @mouseleave="hover = false">
3 A Button
4 </button>
5</template>
6
7<script setup>
8import { computed, ref, normalizeClass } from "vue";
9
10const props = defineProps({
11 disabled: {
12 type: Boolean,
13 default: false
14 },
15 variant: {
16 type: String,
17 default: "default",
18 validator: function (v) {
19 return ["default","outline","plain"].includes(v);
20 }
21 },
22 size: {
23 type: String,
24 default: "md"
25 validator: function (v) {
26 return ["xs","sm","md","lg","xl"].includes(v);
27 }
28 }
29});
30
31const hover = ref(false);
32const buttonClass = computed(() => {
33 return normalizeClass([
34 "btn",
35 `btn--${props.size}`,
36 hover.value ? 'has-hover' : 'no-hover',
37 {
38 'is-default': props.variant === 'default',
39 'is-outline': props.variant === 'outline',
40 'is-plain': props.variant === 'plain'
41 }
42 ]);
43});
44</script>

Final Thoughts

Keeping as much logic out of the template as possible is always laudable goal and choosing when to apply classes is one of the major causes of this logic. The main advantage with using Vue’s internal methods is that you’re usually sure of a robust, well-tested method which works exactly the same as the rest of your code.

Copyright 2007 - 2024 southcoastweb is a brand of DSM Design.