Vue 3.5 Release: What's New and Improved?

Harish Kumar · · 2288 Views

Vue.js has released version 3.5, bringing a host of exciting new features and optimizations designed to boost developer productivity and improve application performance. This update is fully backward-compatible, allowing you to upgrade without concerns about breaking changes. Let’s explore the key enhancements in Vue 3.5 and discover how they can streamline your development process.

Reactive Props Destructure

One of the most developer-friendly features introduced in Vue 3.5 is the stabilization of reactive props destructuring. In previous versions, handling default values for props required a bit of boilerplate. Now, you can simplify your code significantly.

Before Vue 3.5

const props = withDefaults(
  defineProps<{
    count?: number
    msg?: string
  }>(),
  {
    count: 0,
    msg: 'hello'
  }
)

After Vue 3.5

const { count = 0, msg = 'hello' } = defineProps<{
  count?: number
  message?: string
}>()

This new approach not only reduces the amount of code but also aligns better with native JavaScript syntax, making it easier to write and understand.

However, it's important to note that when you want to watch or pass these destructured props into composables while retaining reactivity, you'll need to wrap them in a getter.

Example of Watching a Destructured Prop

watch(count /* ... */)
//    ^ results in compile-time error

watch(() => count, newValue => {
  //   ^ wrap in a getter, works as expected
})

// composables should normalize the input with `toValue()`
useDynamicCount(() => count)

This update is a real time-saver and makes your codebase cleaner and more maintainable.

useTemplateRef(): Simplified and More Flexible Template Refs

Vue 3.5 introduces useTemplateRef(), a new and improved way to manage template refs, making it easier to interact with DOM elements, especially within composables.

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

const inputRef = useTemplateRef('input')
</script>

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

This new API offers greater clarity and flexibility, allowing you to efficiently manage DOM elements within shared logic. For example, you can now use useTemplateRef() in composables, making it easier to access and manipulate DOM elements across multiple components. Here's how you can leverage it in a composable:

// useAutoFocus.js
import { useTemplateRef, onMounted } from 'vue'
 
export function useAutoFocus(refName) {
    const elementRef = useTemplateRef(refName)
 
    onMounted(() => {
        elementRef.value?.focus()
    })
 
    return elementRef
}
<!-- MyComponent.vue -->
<script setup>
import { useAutoFocus } from './useAutoFocus'
 
const inputRef = useAutoFocus('inputRef')
</script>
 
<template>
    <input ref="inputRef" v-model="someData" />
</template>

In this example, we've created a useAutoFocus composable that uses useTemplateRef() to get a reference to an input element and automatically focus on it when the component mounts. This reusable logic simplifies your codebase and can be applied to various components without redundancy. Pretty neat, right?

Deferred Teleport

The <Teleport> component now supports a defer prop, allowing you to delay teleportation until after the render cycle.

<Teleport defer target="#container">...</Teleport>
<div id="container"></div>

onWatcherCleanup()

A globally imported API that simplifies cleaning up side effects in watchers, making it easier to manage asynchronous tasks and other cleanup activities.

import { watch, onWatcherCleanup } from 'vue'

watch(id, (newId) => {
  const controller = new AbortController()

  fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
    // callback logic
  })

  onWatcherCleanup(() => {
    // abort stale request
    controller.abort()
  })
})

SSR Improvements: Lazy Hydration, useId(), and data-allow-mismatch

Server-side rendering (SSR) has received several notable improvements in Vue 3.5, which will be especially beneficial for large-scale applications.

Lazy Hydration

Lazy Hydration allows you to defer the hydration of async components until they are actually needed, such as when they become visible in the viewport. This can drastically improve performance by reducing the initial load time.

import { defineAsyncComponent, hydrateOnVisible } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./MyComponent.vue'),
  hydrate: hydrateOnVisible()
})

useId(): Generating Stable IDs

The new useId() API generates unique IDs that are stable across both server and client renders, preventing hydration mismatches—a common issue in SSR applications.

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

const id = useId()
</script>

<template>
  <form>
    <label :for="id">Name:</label>
    <input :id="id" type="text" />
  </form>
</template>

data-allow-mismatch: Handling Client-Server Differences

Sometimes, the data rendered on the server may differ from what is rendered on the client. With the new data-allow-mismatch attribute, you can suppress warnings for these expected mismatches, providing a smoother user experience.

<span data-allow-mismatch>{{ data.toLocaleString() }}</span>

You can even specify which types of mismatches to allow, such as text, children, class, style, or attribute.

Custom Elements Enhancements

Vue 3.5 has made it easier to work with custom elements, introducing new APIs and options that offer more control and flexibility.

  1. App Configurations: Custom elements can now utilize app configurations via the configureApp option.

  2. Shadow DOM Control: Decide whether to use Shadow DOM with the new shadowRoot: false option.

  3. Accessing Host Elements: Use the new useHost() and useShadowRoot() APIs to interact with the host element and shadow root, making it easier to develop complex custom elements.

Example: Defining a Custom Element Without Shadow DOM

import MyElement from './MyElement.ce.vue'

defineCustomElements(MyElement, {
  shadowRoot: false,
  nonce: 'xxx',
  configureApp(app) {
    app.config.errorHandler = ...
  }
})

These enhancements make custom elements more powerful and easier to integrate into your Vue applications.

Reactivity System Enhancements

Vue's reactivity system has always been a standout feature, and with the release of Vue 3.5, it has seen significant improvements. This version introduces a major overhaul that dramatically reduces memory usage by up to 56%, making your applications more efficient, especially when handling large amounts of data.

In addition to memory optimizations, reactivity tracking for large, deeply nested arrays has been fine-tuned to be up to 10 times faster in certain scenarios. This enhancement is particularly beneficial for managing complex state in your applications.

  1. 56% decrease in memory usage

  2. Up to 10x speed boost for operations on large, reactive arrays

Wrapping Up

Vue 3.5 is a robust update that enhances the framework's performance, usability, and developer experience. Whether you're dealing with large datasets, optimizing SSR, or refining your component architecture, these new features and improvements make Vue an even more powerful tool in your development toolkit.

Since this is a minor release, your existing Vue 3 applications should work seamlessly with these updates. However, as with any update, be sure to thoroughly test your application before deploying to production.

Happy coding with Vue 3.5!

🔥 Supercharge Your Development with Ctrl+Alt+Cheat

I’m super excited to introduce Ctrl+Alt+Cheat, the ultimate cheat sheet extension for VSCode.

👉 Download Ctrl+Alt+Cheat today and start coding like a pro!

0

Please login or create new account to add your comment.

0 comments
You may also like:

Understanding the `.reduce()` Method in JavaScript

The .reduce() method in JavaScript is one of the most powerful array methods used for iterating over array elements and accumulating a single value from them. Whether you're summing (...)
Harish Kumar

Building a Real-Time Chat App with Laravel Reverb and Nuxt 3

Building a real-time chat application is a great way to understand the power of WebSockets and real-time communication. In this tutorial, we will walk through creating a Real-Time (...)
Harish Kumar

How to Use JavaScript’s .every() and .some() for Smarter Array Handling

JavaScript provides a variety of array methods that allow developers to perform common tasks in an efficient, clean, and readable manner. Among these methods are .every() and .some(), (...)
Harish Kumar

How to Set Up Nuxt 3 Authentication with Laravel Sanctum (Step-by-Step Guide)

In modern web development, securing your application’s authentication process is a top priority. For developers building Single Page Applications (SPA) or Server-Side Rendered (...)
Harish Kumar

Understanding `.slice()` and `.splice()`: JavaScript Array Methods

In JavaScript, arrays come with numerous built-in methods for manipulation. Two commonly used methods are .slice() and .splice(). While they sound similar, their purposes and behaviors (...)
Harish Kumar

JavaScript Array .filter(): A Comprehensive Tutorial

JavaScript offers several powerful methods to manipulate arrays, and .filter() is one of the most versatile and commonly used. This tutorial will guide you through the basics of (...)
Harish Kumar