DEV Community

Cover image for Vue 3.5 “Tengen Toppa Gurren Lagann” Innovations: Advanced Features and Most Powerful Updates 🚀
Abdulnasır Olcan
Abdulnasır Olcan

Posted on

Vue 3.5 “Tengen Toppa Gurren Lagann” Innovations: Advanced Features and Most Powerful Updates 🚀

The announcement of Vue 3.5 includes exciting features with new performance optimizations and improvements. This version introduces innovations such as reactivity system enhancements, SSR (Server-Side Rendering) improvements, and new features like custom elements and deferred teleport. Let's take a detailed look at the key features of Vue 3.5 with examples:

1. Reactivity System Enhancements

The performance updates made to the reactivity system in Vue 3.5 deliver significant speed improvements, especially for large data sets.

With optimizations in Vue’s reactivity structure, better memory usage (around 56% savings) and faster reactive processes are achieved. This results in up to a 10x speed increase, particularly in handling large data sets.

This example allows for faster response times when updating complex data lists or tracking computed values.

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

const state = reactive({
  items: Array.from({ length: 10000 }, (_, i) => ({ id: i, value: Math.random() }))
});

const totalValue = computed(() => {
  return state.items.reduce((sum, item) => sum + item.value, 0);
});
</script>

<template>
  <p>Total Value: {{ totalValue }}</p>
</template>
Enter fullscreen mode Exit fullscreen mode

In the example, if you have a list of 10,000 items, you'll observe a faster computation and update process with Vue 3.5.

2. Reactive Props Destructure

In Vue 3.5, defining prop variables reactively with defineProps has become much more streamlined. Now, default values can be assigned to props using JavaScript’s built-in features.

This allows us to assign default values to props with a cleaner syntax.

<script setup>
const { count = 0, msg = 'hello' } = defineProps<{
  count?: number;
  msg?: string;
}>();
</script>

<template>
  <p>Count: {{ count }}</p>
  <p>Message: {{ msg }}</p>
</template>
Enter fullscreen mode Exit fullscreen mode

This usage allows default values to be assigned to the count and msg variables without needing helper functions like withDefaults.

3. SSR Improvements

Vue 3.5 introduces features like Lazy Hydration for Server-Side Rendering (SSR). This enables you to create components that load only when visible to the user.

Additionally, APIs like useId() generate unique IDs that ensure client-server matching, and the data-allow-mismatch attribute prevents error warnings for non-matching client data.

a. Lazy Hydration

With Lazy Hydration, support is provided for components that load only when they become visible.

import { defineAsyncComponent, hydrateOnVisible } from 'vue';

const LazyComponent = defineAsyncComponent({
  loader: () => import('./MyComponent.vue'),
  hydrate: hydrateOnVisible()
});
Enter fullscreen mode Exit fullscreen mode

This feature improves performance by loading components only when displayed, instead of loading the entire page.

b. useId()

useId() creates unique IDs across components in Vue, ensuring consistency on both the client and server sides. This is crucial when IDs are needed, such as for form elements or accessibility purposes.

For instance, if you need a unique ID for each input field in a form, you can dynamically generate these IDs using useId().

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

const id = useId(); // Generates a unique and consistent ID
</script>

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

Enter fullscreen mode Exit fullscreen mode

c. data-allow-mismatch

data-allow-mismatch prevents unnecessary warnings in the client console when data on the server and client sides may naturally mismatch. For example, when using dynamic data like date or time, slight differences might occur between the client and server. This feature suppresses warnings, providing a cleaner experience for the user.

<template>
  <span data-allow-mismatch="text">{{ new Date().toLocaleString() }}</span>
</template>
Enter fullscreen mode Exit fullscreen mode

In this example, using data-allow-mismatch="text" enables the display of date and time. data-allow-mismatch prevents data differences between the client and server from being perceived as errors and only suppresses mismatches of type "text." Additionally, specific values like text, children, class, style, and attribute can be used for data-allow-mismatch.

4. Custom Elements Enhancements

The defineCustomElement API provides more options for creating custom HTML elements even without Shadow DOM. New APIs like useHost() and useShadowRoot() also allow access to the shadow root.

a. Accessing Element and Shadow Root with useHost and useShadowRoot

With Vue 3.5’s useHost and useShadowRoot APIs, you can access and manage the properties of your custom component via the shadow root.

import { defineCustomElement, useHost, useShadowRoot } from 'vue';

export default defineCustomElement({
  setup() {
    const host = useHost(); // Access to the main root of the element
    const shadowRoot = useShadowRoot(); // Access to the Shadow DOM root

    // Custom operations can be performed using the shadow root
    return { host, shadowRoot };
  }
});

Enter fullscreen mode Exit fullscreen mode

With these features, you can manage specific operations tied to the custom element via host or shadowRoot, allowing the component to run smoothly even in systems outside of Vue.

b. Creating a Basic Custom Element with defineCustomElement

In Vue, you can use the defineCustomElement API to register a component as a custom HTML element. For example, let’s create a component called “CustomButton”:

// CustomButton.ce.vue
<script setup>
const handleClick = () => {
  alert('Button clicked!');
};
</script>

<template>
  <button @click="handleClick">Click Me!</button>
</template>
Enter fullscreen mode Exit fullscreen mode

Let's define our component as a custom element using defineCustomElement:

// main.js
import { defineCustomElement } from 'vue';
import CustomButton from './CustomButton.ce.vue';

const CustomButtonElement = defineCustomElement(CustomButton);
customElements.define('custom-button', CustomButtonElement);
Enter fullscreen mode Exit fullscreen mode

In this example, the CustomButton component becomes usable with the <custom-button> tag. This custom element can now be integrated into another application and function as an independent component.

c. Using Shadow DOM

In Vue 3.5, you can add an option within defineCustomElement to enable or disable the Shadow DOM. The Shadow DOM encapsulates the component’s styles and DOM structure, preventing conflicts with other styles.

With these features, you can create custom HTML elements in Vue and enable broad usage without requiring the Shadow DOM.

import { defineCustomElement } from 'vue';
import CustomButton from './CustomButton.ce.vue';

const CustomButtonElement = defineCustomElement(CustomButton, { shadow: true });
customElements.define('custom-shadow-button', CustomButtonElement);
Enter fullscreen mode Exit fullscreen mode

In this example, the shadow: true setting allows the component to operate within the Shadow DOM. To disable the Shadow DOM, you can set it to shadow: false.

5. useTemplateRef()

Vue 3.5 introduces the useTemplateRef() API, allowing you to define dynamic references easily. With this feature, you can manage refs based on variable IDs rather than being static.

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

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

<template>
  <input ref="input">
</template>
Enter fullscreen mode Exit fullscreen mode

useTemplateRef provides easier usage for elements with dynamically changing IDs.

6. Deferred Teleport

In Vue 3.5, the defer attribute added to the <Teleport> component allows content to move before the DOM is fully ready. This is especially useful for transferring late-loading content to target elements within Vue.

<Teleport defer to="#target">
  <div>Content teleported to #target after mount</div>
</Teleport>
<div id="target"></div>
Enter fullscreen mode Exit fullscreen mode

This example demonstrates that you can transfer content even when the target element is not yet present in the DOM.

7. onWatcherCleanup()

With Vue 3.5, onWatcherCleanup() more effectively manages cleanup operations within watchers.

import { watch, onWatcherCleanup } from 'vue';

watch(id, (newId) => {
  const controller = new AbortController();
  fetch(`/api/${newId}`, { signal: controller.signal });

  onWatcherCleanup(() => {
    controller.abort(); // Stops the operation when the watcher is stopped
  });
});

Enter fullscreen mode Exit fullscreen mode

In this example, onWatcherCleanup prevents unnecessary network traffic by canceling outdated requests.

These are the highlighted features in the Vue 3.5 announcement. For more details and additional examples, you can check out the official blog post.

Happy coding! 🚀

Top comments (0)