Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Reactivity

ref()

ref() wraps a value in a reactive object, allowing Vue to track changes to that value and update the DOM accordingly. This is the recommended way to create reactive primitive values. shallowRef() is the shallow version of ref(), which opt-out of deep reactivity for the value it holds.

<template>
  <div>
    <p>Count is: {{ count }}</p>
    <button @click="count++">Increment</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";

const count = ref(0);

console.log(count); // { value: 0 }
console.log(count.value); // 0

count.value++;
console.log(count.value); // 1
</script>

reactive()

reactive() creates a reactive object from a plain JavaScript object. It makes an object itself reactive. shallowReactive() is the shallow version of reactive(), which opt-out of deep reactivity for the properties it holds.

<template>
  <div>
    <button @click="state.count++">{{ state.count }}</button>
  </div>
</template>

<script setup lang="ts">
import { reactive } from "vue";

const state = reactive({ count: 0 });
</script>

It is important to note that the returned value from reactive() is a Proxy of the original object, which is not equal to the original object. Only the proxy is reactive - mutating the original object will not trigger updates.

computed()

<script setup>
import { reactive, computed } from "vue";

const author = reactive({
  name: "John Doe",
  books: [
    "Vue 2 - Advanced Guide",
    "Vue 3 - Basic Guide",
    "Vue 4 - The Mystery",
  ],
});

// a computed ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? "Yes" : "No";
});
</script>

watch()

<script setup>
import { ref, watch } from "vue";

const question = ref("");
const answer = ref("Questions usually contain a question mark. ;-)");
const loading = ref(false);

// watch works directly on a ref
watch(question, async (newQuestion, oldQuestion) => {
  if (newQuestion.includes("?")) {
    loading.value = true;
    answer.value = "Thinking...";
    try {
      const res = await fetch("https://yesno.wtf/api");
      answer.value = (await res.json()).answer;
    } catch (error) {
      answer.value = "Error! Could not reach the API. " + error;
    } finally {
      loading.value = false;
    }
  }
});
</script>

<template>
  <p>
    Ask a yes/no question:
    <input v-model="question" :disabled="loading" />
  </p>
  <p>{{ answer }}</p>
</template>