Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

The Essence of Vue Reactivity: Linking Data and Functions

Tech 1

1. The Essence of Reactivity

Reactivity is about linking data and functions together. When the data changes, the associated functions automatically execute. However, there are constraints on what qualifies as a function and what qualifies as data.

Functions that participate in reactivity:

  • render
  • computed
  • watch
  • watchEffect

Data that participates in reactivity:

  • Reactive data (e.g., ref, reactive)
  • Data that is used inside one of the above functions

2. Examples

2.1 A Non-Reactive Example

<template>
  <div class="responsive">
    <h1>Reactivity Example</h1>
    <div>Passed value: {{ count }}</div>
    <br>
    <div>Doubled: {{ doubled }}</div>
  </div>
</template>

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

const props = defineProps({
  count: {
    type: Number,
    default: 0
  }
})

const doubled = ref(props.count * 2)
</script>

Result: The page does not update when the count prop changes. This is because doubled is not reactive. The assignment ref(props.count * 2) happens once and does not involve any function that tracks dependencies. Data-to-data links are not automatically reactive.


2.2 Using watchEffect to Make It Reactive

<template>
  <div class="responsive">
    <h1>Reactivity Example</h1>
    <div>Passed value: {{ count }}</div>
    <br>
    <div>Doubled: {{ doubled }}</div>
  </div>
</template>

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

const props = defineProps({
  count: {
    type: Number,
    default: 0
  }
})

const doubled = ref(0)

watchEffect(() => {
  doubled.value = props.count * 2
})
</script>

Result: The page updates when the count prop increases. Why?

  1. watchEffect is a function, and props.count is reactive data used inside it. So when props.count changes, the watchEffect callback runs, updating doubled.value.
  2. doubled is also reactive data, and it is used in the render function. When doubled changes, the render function re-executes, updating the DOM.

2.3 Passing a Primitive Value to a Function

<template>
  <div class="responsive">
    <h1>Reactivity Example</h1>
    <div>Passed value: {{ count }}</div>
    <br>
    <div>Doubled: {{ doubled }}</div>
  </div>
</template>

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

const props = defineProps({
  count: {
    type: Number,
    default: 0
  }
})

function useDoubled(value) {
  const result = ref(0)
  watchEffect(() => {
    result.value = value * 2
  })
  return result
}

const doubled = useDoubled(props.count)
</script>

Result: The page does not update when the count prop changes. Why? The useDoubled function receives props.count as a primitive number. Inside watchEffect, it uses value which is just a number—not a reactive reference. Therefore, no dependency is tracked, and the effect never reruns.


2.4 Using computed

<template>
  <div class="responsive">
    <h1>Reactivity Example</h1>
    <div>Passed value: {{ count }}</div>
    <br>
    <div>Doubled: {{ doubled }}</div>
  </div>
</template>

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

const props = defineProps({
  count: {
    type: Number,
    default: 0
  }
})

const doubled = computed(() => {
  return props.count * 2
})
</script>

Result: The page updates when the count prop changes. Why?

  1. computed is a function that reads props.count (reactive). So computed tracks props.count and recalculates whenever it changes.
  2. doubled (the computed ref) is reactive and used in the render function, so changing it triggers a re-render.

2.5 Passing the Entire Props Object

<template>
  <div class="responsive">
    <h1>Reactivity Example</h1>
    <div>Passed value: {{ count }}</div>
    <br>
    <div>Doubled: {{ doubled }}</div>
  </div>
</template>

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

const props = defineProps({
  count: {
    type: Number,
    default: 0
  }
})

function useDoubled(propsObj) {
  const result = ref(0)
  watchEffect(() => {
    result.value = propsObj.count * 2
  })
  return result
}

const doubled = useDoubled(props)
</script>

Result: The page updates when the count prop changes. Why?

  1. props is a reactive object. When we pass props to useDoubled, the watchEffect inside it reads propsObj.count. Since propsObj is reactive, the effect tracks the count property.
  2. When count changes, the effect runs, updating doubled.
  3. doubled is reactive and used in the render function, so the view updates.

Note: This pattern (passing the whole props object) is common in libraries like VueUse.

Summary

Reactivity in Vue depends on establishing a connection between reactive data and functions (render, computed, watch, watchEffect). A direct assignment between two reactive values without an intervening reactive function will not be tracked. To create a reactive derivation, always use computed or a watcher inside a setup scope that reads the reactive source.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.