Computer scienceFrontendVue.jsComputable Properties

Getters and setters

8 minutes read

Getters and setters are the cornerstone of of Vue's reactivity system, offering a robust way to compute and modify values as your application's state evolves. Getters compute values based on reactive properties, while setters modify them. In this topic, we will dive into the realm of Vue's getters and setters, uncovering how to effectively employ them to improve your Vue applications.

Understanding getters and setters

In Vue, computed properties are an essential tool to calculate values based on other reactive properties. Getters and setters play a crucial role in computed properties, allowing you to both get and set values concisely and elegantly.

A getter is a function that calculates and returns a value based on one or more reactive properties. It allows you to retrieve a computed value just like a regular property. Getters are especially useful for transforming or filtering data before displaying it.

A setter, on the other hand, is a function that allows you to update the value of a reactive property. When you modify a property managed by a setter, it triggers a reactivity update and can cause related computed properties to recalculate.

Now, let's see how you can create getters and setters in Vue.

Creating getters and setters

In the below example, we'll create a simple counter component with a getter to double the count and a setter to update the count value.

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button type="button" @click="incrementCount">Increment</button>
    <p>Double Count: {{ doubleCount }}</p>
    <button type="button" @click="setCountManually">Set Count Manually</button>
  </div>
</template>

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

// Define the count and setCount (setter)
const count = ref(0);
const setCount = (value) => {
  count.value = value;
};

// Define a getter to double the count
const doubleCount = computed(() => count.value * 2);

// Function to increment the count
const incrementCount = () => {
  count.value++;
};

// Function to set count manually
const setCountManually = () => {
  setCount(10); // Set the count to 10 using the setter
};
</script>

In the above example, we define the count using ref and a setCount function, which acts as a setter to update the count value. Then, we create a getter called doubleCount using the computed function, which calculates double the value of count. In the template, we display the current count value, a button to increment the count, the doubleCount, and a button to set the count manually. Take your time to run the code and observe the output.

When you click the "Increment" button, the incrementCount() function is called, which increases the count value. The doubleCount automatically updates due to the getter.

When you click the "Set Count Manually" button, the setCountManually function is called, which uses the setter to set the count to 10. This change triggers an update in the doubleCount as well.

Getters and setters in this example allow for a clear separation of concerns and reactivity, making it easy to calculate and manage the count value in a structured manner.

Here's the result of the above code:

Output image of the getters and setters

Usage and examples

1. Validation and Formatting: You can use getters and setters to validate and format data before it is displayed or stored. For instance, you can ensure that a user's input adheres to specific rules, such as restricting the length of a text field or formatting dates consistently.

<script setup>
const userInput = ref('');

const formattedInput = computed({
  get: () => userInput.value,
  set: (newValue) => {
    // Perform validation and formatting here
    userInput.value = newValue;
  },
});
</script>

2. Dependency Management: Getters and setters are excellent for managing dependencies. If you need to react to changes in one piece of state when another changes, you can use getters to define the dependency and setters to update it.

<script setup>
const count = ref(0);

const doubleCount = computed({
  get: () => count.value * 2,
  set: (newValue) => {
    count.value = newValue / 2;
  },
});
</script>

3. In Vue, one of the most common scenarios where getters and setters shine is when working with custom input components that use the `v-model` directive for two-way data binding. Let's explore this by creating a custom input component and using getters and setters to manage its value.

<!-- ChildComponent.vue -->

<template>
  <div>
    <label for="inputValue">Enter a Number:</label>
    <input type="number" id="inputValue" v-model="modelValue" />
    <p>Double the Value: {{ doubleValue }}</p>
  </div>
</template>

<script setup>
import { ref, computed, defineProps, defineEmits } from 'vue'

// Define a prop for v-model binding
const modelValue = defineProps(['modelValue'])

// Getter to double the input value
const doubleValue = computed({
  get: () => modelValue.value * 2,
  set: (newValue) => {
    // Use emit to update the prop value
    const emit = defineEmits()
    emit('update:modelValue', newValue)
  }
})
</script>
<!-- ParentComponent.vue -->

<template>
  <div>
    <h2>Parent Component</h2>
    <ChildComponent v-model="parentValue" />
    <p>Parent Value: {{ parentValue }}</p>
  </div>
</template>

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

const parentValue = ref(0)
</script>

In the above example, we created a ChildComponent, that incorporates the v-model directive for two-way data binding. It defines a modelValue prop for this binding and computes a doubleValue property, acting as a getter and setter. When a number is entered in the input field, the v-model directive keeps both the input field and the modelValue prop in sync.

The computed doubleValue getter calculates and displays double the input value, and the setter uses the emit method to update the modelValue prop, ensuring changes made in the child component are reflected in the parent component. The ParentComponent imports the child component and passes parentValue as the bound prop using v-model, demonstrating the parent-child relationship and how getters and setters work with the v-model directive to maintain synchronized data.

Limitations and best practices

While getters and setters in Vue 3 Composition API are flexible, they come with certain limitations and require adherence to best practices to ensure effective and maintainable code.

Limitations

  • Avoid Circular Dependencies: Circular dependencies occur when computed properties depend on each other in a way that creates an infinite loop. Vue provides a warning when this happens, but it's essential to design your code to prevent such situations.

  • Performance Impact: Overusing computed properties with complex getters and setters can have a performance impact. Excessive reactivity can lead to unnecessary calculations and updates, so it's essential to strike a balance between reactivity and performance.

  • Complexity: When you use numerous getters and setters in your code, it can become more challenging to understand and maintain. Keep your codebase clean and simple to minimize potential issues.

Best Practices

  • Use Computed Properties for Complex Logic: For more complex calculations or logic, it's often better to use computed properties instead of adding complexity to your getters and setters. Computed properties are easier to test, debug, and understand.
  • Separate Concerns: Avoid mixing presentation logic with data manipulation in your getters and setters. Keeping concerns separate makes your code more modular and easier to maintain.
  • Optimize for Performance: Be mindful of the performance implications of reactive code. Use the watchEffect and watch functions for scenarios where you don't need reactivity, and use ref or reactive only when necessary.

Conclusion

Getters and setters enable you to encapsulate and manage the state and behavior of your Vue components, offering a concise and elegant means to derive and update data. Whether you're using them for data transformation, validating input, managing dependencies, or performing reactive calculations, getters and setters have a wide range of practical applications that improve the maintainability and performance of your Vue applications.

2 learners liked this piece of theory. 1 didn't like it. What about you?
Report a typo