Vue as most of us know, has gone through a lot of changes mainly introduced through the composition API, in this article, I started a guide to help new Vue lovers or those trying to move from other frameworks to VueJs. I will make more articles to cover more related concepts.
-
Template syntax: Basically here you will learn about the
<template> <template/>
part found in any in any SFC (Single File Component) -
Reactivity : Here you will learn about how you interact with data (creation, accessibility,...). also you will learn about
ref()
andreactive()
which will help you deal with that, you will learn the difference between both of them and you'll get to decide when to use each one.
The reason why ref
is used for single values, while reactive
is used for objects or nested data structures, lies in the way Vue 3's reactivity system works under the hood.
ref
for single values:
The ref
function is designed to handle the reactivity of single, primitive values like strings, numbers, and booleans. These values are known as "plain old data" or "immutable data" because they cannot be modified directly; instead, they need to be reassigned to a new value.
When you create a reactive reference using ref(value)
, Vue internally wraps the value in an object and creates a getter and setter for the .value
property. This allows Vue to track changes to the value and trigger updates whenever the .value
property is reassigned.
Here's a simplified example of how ref
works internally:
function ref(value) {
const wrapper = {
value,
get value() {
// Track dependency
return value
},
set value(newValue) {
// Trigger updates
value = newValue
}
}
return wrapper
}
By using .value
to access and update the value, Vue can properly track dependencies and trigger updates when necessary.
reactive
for objects and nested data structures:
On the other hand, the reactive
function is designed to handle the reactivity of objects and nested data structures, such as arrays, objects, and more complex data types. These data structures are known as "mutable data" because their properties or elements can be directly modified.
When you create a reactive object using reactive(obj)
, Vue internally "proxies" the object, which means it creates a special proxy object that wraps the original object. This proxy object intercepts property access and mutations on the original object, allowing Vue to track dependencies and trigger updates accordingly.
Here's a simplified example of how reactive
works internally:
function reactive(obj) {
const proxy = new Proxy(obj, {
get(target, key) {
// Track dependency
return target[key]
},
set(target, key, value) {
// Trigger updates
target[key] = value
return true
}
})
return proxy
}
By using the proxy object, Vue can intercept property access and mutations, track dependencies, and trigger updates when necessary.
The reason reactive
is preferred for objects and nested data structures is that it provides a more efficient and straightforward way to handle reactivity for these complex data types. With ref
, you would need to create multiple reactive references for each property or element, which can become cumbersome and less efficient for larger data structures.
Additionally, using reactive
for objects and nested data structures better aligns with the way developers typically work with these data types in JavaScript, making the code more intuitive and easier to reason about.
In summary, ref
is used for single, primitive values because it provides a simple way to create reactive references and track changes to these immutable data types. reactive
, on the other hand, is used for objects and nested data structures because it leverages the power of proxies to efficiently handle reactivity for mutable data types, while preserving the natural way of working with objects and arrays in JavaScript.
- Computed properties : They are basically 'automatically calculated variables', they can be used in both template and script parts in vue components. Generally we use them to get a value or an object that changes based other value(s). ex:
<script setup>
import { reactive, computed } from 'vue'
const input = ref({
weight: 82,
height: 1,70
})
// a computed ref
const bmi = computed(() => { return input.weight/(Math.sqrt(input.height)) })
</script>
<template>
<span>Your BMI is: {{ bmi }}</span>
</template>
- Class/Style binding : Here you will mainly learn about how you can interact with your css using data binding to make it adapt to any situation you come across. Ex: conditionally apply a dark mode styling depending on the value returned from a dark mode toggle
- Directives Also knows as life saviors hhhhh, they are special HTML attributes with the prefix v- that give the HTML tag extra functionality. Better check the difference between v-if and v-show to learn more about conditional rendering. also check List rendering using v-for
-
Event Handling : In Vue.js, event handling allows you to respond to user interactions, such as clicks, input changes, and other DOM events. Here's a summary of event handling in Vue.js:
1. Handling DOM Events:
-
v-on Directive:
- The
v-on
directive is used to attach event listeners to DOM elements. - It can be used in various ways, such as
v-on:click
,v-on:input
, etc.
- The
-
Shorthand for v-on:
- Vue provides a shorthand for
v-on
using the@
symbol. For example,@click
is equivalent tov-on:click
.
- Vue provides a shorthand for
-
v-on Directive:
2. Methods for Event Handling:
-
Event Handling Methods:
- You can define methods in your Vue instance or component and call them when an event occurs.
-
Example:
<button v-on:click="handleClick">Click me</button>
```
new Vue({
methods: {
handleClick() {
console.log('Button clicked!');
}
}
});
```
-
Passing Parameters:
- You can pass additional parameters to your methods using the
v-on
directive. -
Example:
<button v-on:click="handleClick('Hello')">Click me</button>
- You can pass additional parameters to your methods using the
```
new Vue({
methods: {
handleClick(message) {
console.log('Button clicked with message:', message);
}
}
});
```
3. Event Modifiers:
-
Preventing Default:
- Use the
.prevent
modifier to prevent the default behavior of an event. -
Example:
<form v-on:submit.prevent="handleSubmit">Submit</form>
- Use the
-
Stop Propagation:
- Use the
.stop
modifier to stop the event propagation. -
Example:
<div v-on:click.stop="handleClick">Click me</div>
- Use the
-
Key Modifiers:
- You can use key modifiers to respond to specific keys. For example,
@keydown.enter
.
- You can use key modifiers to respond to specific keys. For example,
4. Inline Statements:
-
Inline Event Handling:
- You can also handle events directly in the template using inline statements.
-
Example:
<button @click="() => { console.log('Button clicked!'); }">Click me</button>
5. Custom Events:
-
Custom Event Handling:
- Components can emit custom events to communicate with their parent components.
-
Example:
<!-- Child Component --> <button @click="notifyParent">Click me</button> <script> methods: { notifyParent() { this.$emit('custom-event', 'Hello from child!'); } } </script>
```
<!-- Parent Component -->
<child-component @custom-event="handleCustomEvent"></child-component>
<script>
methods: {
handleCustomEvent(message) {
console.log('Received custom event:', message);
}
}
</script>
```
These are the fundamental concepts of event handling in Vue.js. Understanding these concepts will help you create interactive and responsive Vue.js applications.
-
Form Binding : Here you will learn about how to your template will interact with your data, whether how your is fed to a form or how you go from data in your
<textarea/>
input to a property in an object - Component lifecycle : This is where you will learn about the different series of initialization steps a component goes through when it's created and how you can use them for your advantage, Ex: thanks to onMounted() hook, you can load your table data right when the component is mounted. - Watchers : You can consider them as literal data surveillance dogs. you can program them to make any callback. right after the value of a property changes and they can be configured too. In Vue 3's Composition API, bothwatch
andwatchEffect
are functions used for reactively watching data sources, but they differ in their behavior and use cases. Here's an explanation of the differences between them:
watch
:
The watch
function is used to watch one or more reactive data sources and perform side effects or update other reactive data based on the changes. It takes two arguments: a source (reactive data source or getter function) and a callback function.
Example:
import { ref, watch } from 'vue'
const count = ref(0)
const doubled = ref(0)
watch(count, (newCount, oldCount) => {
doubled.value = newCount * 2
})
In this example, watch
observes changes to the count
reactive reference and updates the doubled
reactive reference with the new doubled value whenever count
changes.
The watch
function is useful when you need to perform side effects or update other reactive data based on changes to specific data sources.
watchEffect
:
The watchEffect
function is a more low-level and powerful way to reactively watch data sources. It takes a single function as an argument, and this function is automatically re-executed whenever any of its reactive dependencies (data sources it accesses) change.
Example:
import { ref, watchEffect } from 'vue'
const count = ref(0)
const doubled = ref(0)
watchEffect(() => {
doubled.value = count.value * 2
})
In this example, watchEffect
automatically tracks the reactive dependencies (in this case, count
) inside its callback function. Whenever count
changes, the callback function is re-executed, and doubled
is updated with the new doubled value.
The key difference between watchEffect
and watch
is that watchEffect
automatically tracks dependencies, while watch
requires you to explicitly specify the data sources to watch.
watchEffect
is useful when you have a complex computation or side effect that depends on multiple reactive data sources, and you don't want to explicitly list all of them in a watch
call.
Here are some additional differences between watch
and watchEffect
:
-- Cleanup: The callback function passed to watchEffect
can optionally return a cleanup function, which will be called before the effect is re-executed or the component is unmounted. This is useful for cleaning up side effects like timers or event listeners. In contrast, watch
does not provide a built-in mechanism for cleanup.
-- Lazy Initialization: watchEffect
is lazy, meaning it will not execute its callback function until its reactive dependencies are accessed for the first time. This can be useful for performance optimization. watch
, on the other hand, will execute its callback immediately after the component is mounted.
-- Manual Invalidation: watchEffect
provides a way to manually invalidate and re-execute the effect using the watchEffect
function's return value (an invalidate
function). This can be useful for handling external data sources or manually triggering updates. watch
does not provide a similar mechanism.
-
Template Refs : While Vue's declarative rendering model abstracts away most of the direct DOM operations for you, there may still be cases where we need direct access to the underlying DOM elements. To achieve this, we can use the special
ref
-
Component Basics here you will learn about:
- Defining a Component
- Using a Component
- Passing Props
- Listening to Events
- Content Distribution with Slots
- Dynamic Components
Top comments (2)
I also remember the reasoning you use in the part about ref/reactive from the days I was learning Vue.js, but Vue team now recommends
ref
to be used in favor ofreactive
even for complex structures. The convenience of not having to write.value
in script part is paid with several gotchas as discussed in the docs.Personally I think having these two options with so different behavior, is one of the biggest source of confusion for newcomming devs willing to learn Composition API style. Would be better to drop
reactive
completely, but I know this is unlikely to happen.Welcome!
I hope you'll share more Vue related content in the future.