Understanding and Using "ref" in Vue 3

Vue 3, the latest iteration of the popular JavaScript framework, brings a multitude of features and improvements that enhance the development experience. Among these, the ref function stands out as a vital tool for Vue developers. In this blog post, we'll dive into what ref is, how it works in Vue 3, and its practical applications in building reactive interfaces.

What is ref in Vue 3?

In Vue 3, ref is a function imported from the Vue package that creates a reactive reference to a value. When you wrap a value with ref, Vue tracks changes to that value, ensuring the UI updates whenever the value changes. This is part of Vue's reactivity system, which is now powered by JavaScript's Proxy object.

Syntax and Basic Usage

import { ref } from 'vue';

const myValue = ref(initialValue);

Here, myValue becomes a reactive reference to initialValue. It's important to note that to access or modify the value of myValue, you need to use myValue.value.

How Does ref Work?

Under the hood, Vue 3's reactivity system uses Proxies to observe changes to values. When you use ref, it creates a reactive and mutable object with a single property value. This value property is the actual data you want to be reactive. Whenever you access or modify myValue.value, Vue tracks these changes and updates the DOM accordingly.

Practical Applications of ref

1. Local State in Components

One of the most common uses of ref is to manage local state within a component. For example, you might use ref to keep track of a user's input in a form.

<script setup>
import { ref } from 'vue';

const username = ref('');
</script>

In your template, you can easily bind this reactive reference:

<input v-model="username.value" />

2. Reactive Properties Outside of data Option

In Vue 2, reactive properties were typically declared inside the data option of a component. With Vue 3 and the Composition API, ref allows you to define reactive properties outside the data option, giving you more flexibility in structuring your component's logic.

3. Interacting with DOM Elements

ref can also be used to create a reference to a DOM element. This is particularly useful when you need to directly interact with an element, like focusing on an input or integrating with third-party libraries that need direct DOM access.

<script setup>
import { ref, onMounted } from 'vue';

const inputEl = ref(null);

onMounted(() => {
  inputEl.value.focus();
});
</script>

<template>
  <input ref="inputEl" />
</template>

Advanced Example

<template>
  <div>
    <input v-model="newTaskTitle" @keyup.enter="addTask" placeholder="Add a new task" />
    <ul>
      <li v-for="task in filteredTasks" :key="task.id">
        <input type="checkbox" v-model="task.completed" />
        <span :class="{ completed: task.completed }">{{ task.title }}</span>
        <button @click="removeTask(task.id)">Delete</button>
      </li>
    </ul>
    <button @click="showCompleted = !showCompleted">
      Show {{ showCompleted ? 'Active' : 'Completed' }} Tasks
    </button>
  </div>
</template>

<script>
import { ref, computed, watch, onMounted } from 'vue';

export default {
  setup() {
    const tasks = ref([]);
    const newTaskTitle = ref('');
    const showCompleted = ref(false);

    const filteredTasks = computed(() => {
      return tasks.value.filter(task => 
        showCompleted.value ? task.completed : !task.completed
      );
    });

    function addTask() {
      if (newTaskTitle.value.trim() !== '') {
        tasks.value.push({
          id: Date.now(),
          title: newTaskTitle.value,
          completed: false,
        });
        newTaskTitle.value = '';
      }
    }

    function removeTask(id) {
      tasks.value = tasks.value.filter(task => task.id !== id);
    }

    watch(tasks, (newTasks) => {
      console.log('Tasks updated:', newTasks);
    }, { deep: true });

    onMounted(() => {
      console.log('Component is mounted');
    });

    return { tasks, newTaskTitle, filteredTasks, addTask, removeTask, showCompleted };
  }
};
</script>

<style>
.completed {
  text-decoration: line-through;
}
</style>

Explanation

  • Template: Provides an input to add new tasks, a list to display tasks, and a button to toggle between showing completed and active tasks.

  • Reactive State (ref): tasks, newTaskTitle, and showCompleted are reactive states. tasks is an array of task objects, newTaskTitle tracks the input field value, and showCompleted toggles the visibility of tasks.

  • Computed Property (computed): filteredTasks is a computed property that returns tasks based on the showCompleted state.

  • Methods: addTask adds a new task to the tasks array, and removeTask removes a task by its id.

  • Watchers (watch): A watcher is used to log to the console whenever the tasks array changes.

  • Lifecycle Hook (onMounted): The onMounted hook logs a message when the component is mounted to the DOM.

This example is a comprehensive demonstration of various Vue 3 Composition API features, including ref, and it provides a solid foundation for building more complex Vue applications.

Conclusion

Vue 3's ref function is a powerful tool in the Vue developer's arsenal. It simplifies the way we handle reactivity, making it easier to manage state and interact with the DOM. As you build Vue applications, ref will likely become a fundamental part of your development process, helping you write cleaner, more efficient code.

Remember, the key to mastering Vue, or any framework, is practice and exploration. So, experiment with ref and the Composition API to discover the many creative ways you can enhance your Vue applications.

Previous
Previous

Mastering SQLMock for Effective Database Testing

Next
Next

Mastering Performance Testing in Go with Vegeta