Notes

Data models with Vue 3

Usage of JavaScript classes for application models.

Introduction

Usage of JavaScript classes to define models has the advantage to be very declarative and has some interesting features such as getters and methods. However, with the Vue 3 reactivity system, it is generally not recommended to use JavaScript classes to manage a reactive state. Instead, we could use the ref() and reactive() API.

Utility

To make it more declarative, we must define a utility that would wrap data with reactive() so all properties are easily accessible.

export function defineModel(define) {
  return (data) => reactive(define(data))
}

Definition

Then, define a simple model with its data:

export const Post = defineModel((data) => {
  const title = data.title

  return { title }
})

and use in component:


<script setup>
const post = Post({ title: 'How to make cookies' })

post.title = 'How to bake cookies' // { title: 'How to bake cookies' }
</script>

Getters

Now, let's say our post needs a slug, depending on the title property. To do that, we can use the computed() function:

export const Post = defineModel((data) => {
  const title = data.title
  const slug = computed(() => slugify(title.value))

  return { title, slug }
})

Usage:

const post = ref(null)

const { data } = await fetchPost()

post.value = Post(data)
// { title: 'How to make cookies', slug: 'how-to-make-cookies' }

post.value.title = 'How to bake cookies'
// { title: 'How to bake cookies', slug: 'how-to-bake-cookies' }