Vue 3 - How to use reactive ref and computed without .value?

Viewed 10520

When we use Options API, we can define some properties in the computed section and some properties in the data section. All of them become accessible from the instance through the this reference, i.e. in the same object. It's very suitable.

For example:

if (this.hasMore) {
   this.loading = true;
   ...
}

Where hasMore is a computed property, loading is a reactive property.

Is there any possibility to do something similar via Composition API? For example, to implement similar code, but where pagination is a simple object, not a link to a component, like:

if (pagination.hasMore) {
   pagination.loading = true;
   ...
}

The computed is not solution at all, because it returns ref and its using will be completely different than using of this in the example above.

2 Answers

You could use a reactive object having a property which is a computed. Then it will all be accessible the way you want:

const pagination = reactive({
  loading: false,
  hasMore: computed(() => {
    return true;
  })
})

Demo:

const { createApp, reactive, computed } = Vue;
const app = createApp({
  setup() {
    const pagination = reactive({
      loading: false,
      hasMore: computed(() => {
        return true;
      })
    })
    if (pagination.hasMore) {
      pagination.loading = true;
    }
    return {
      pagination
    }
  }
});
app.mount("#app");
<div id="app">
  {{ pagination }}
</div>

<script src="https://unpkg.com/vue@next"></script>

If you really dislike having to use .value with ref you might be interested in the proposed Reactivity Transform proposal which will allows you to use ref without .value. Follow the discussion here: https://github.com/vuejs/rfcs/discussions/369

// declaring a reactive variable backed by an underlying ref
let count = $ref(1)
console.log(count); //no .value needed!

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue({ reactivityTransform: true })]
})
Related