vue3. New features of version 2

Posted by interactive on Sat, 05 Mar 2022 17:43:06 +0100

Vue version 3.2 includes many important new features and performance improvements, but does not include major changes.
Vue 3.2 original link

The main updates are as follows:

1. New single file component function

< script setup > is a compile time syntax sugar, which can greatly improve work efficiency when using Composition API in SFC.
< style > v-bind enables component state driven dynamic CSS values in SFC tags< style>

At first vue3 0 exposed variables must be return ed before they can be used in the template

<script>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export default {
  setup (props) {
  	console.log(props)
  	return {
  	  ok: Math.random(),
  	  Foo,
  	  Bar
  	}
  }
}
</script>

vue3. In 2, you only need to add the setup attribute on the script tag. During the compilation of the component, the code runs up and down in the setup() function. All ES module exports are considered values exposed to the context and are included in the setup() return object.

<template>
  <Foo/>
  <Bar/>
  <component :is="ok ? Foo : Bar"/>
</template>

<script setup="props">
export { default as Foo } from './Foo.vue'
export { default as Bar } from './Bar.vue'
export const ok = Math.random()
console.log(props)
</script>

In fact, script setup is equivalent to running the code in the setup function during compilation, and then defining the exported variables into the context and including them in the returned objects.

style v-bind uses the following:

<template> 
	<button @click="color = color === 'red' ? 'green' : 'red'"> Color is: {{ color }} </button>
</template>

<script setup>
import { ref } from 'vue'
export const color = ref('red')
</script>

<style scoped>
	button { color: v-bind(color);}
</style>

2. Web components

Web Components are a different set of technologies that allow you to create reusable custom elements -- encapsulate their functionality with the rest of the code -- and use them in your web applications.

Vue 3.2 introduces a new way to easily create native custom elements using Vue component API s: defineCustomElement

import { defineCustomElement } from 'vue'
 
const MyVueElement = defineCustomElement({
  // normal Vue component options here
})
 
// Register the custom element.
// After registration, all `<my-vue-element>` tags
// on the page will be upgraded.
customElements.define('my-vue-element', MyVueElement)

Learn more about web components:
Web_Components
web-components-examples

3. Performance improvement

It is mainly reflected in the improvement of interface rendering speed and the reduction of memory usage:

  • More efficient ref implementation (about 260% read speed / about 50% write speed)
  • About 40% faster dependency tracking
  • Memory usage reduced by about 17%
    The template compiler has also been improved:
  • The speed of creating ordinary element VNode is increased by about 200%

Finally, a new v-memo instruction provides the ability to remember part of the template tree. A v-memo allows Vue to skip virtual DOM version comparison and create new virtual nodes. Although rarely required, it provides an escape pod to squeeze out maximum performance in some cases (such as large v-for lists).

4. Server rendering

The package in 3.2 now provides an ES module build, which is also related to node JS built-in module separation. This enables bundling and leveraging non node JS runtime (such as CloudFlare Workers or Service Workers) becomes possible@ vue/server-renderer

@vue/server-renderer

5. Effect range API

3.2 a new Effect Scope API (effectScope, getCurrentScope, onScopeDispose, etc.) is introduced to directly control the processing time of reactivity effects (calculation and observer). It makes it easier to leverage Vue's responsive API outside the component context, and also unlocks some advanced use cases inside the component.

function effectScope(detached?: boolean): EffectScope
interface EffectScope {
  run<T>(fn: () => T): T | undefined // undefined if scope is inactive
  stop(): void
}


const scope = effectScope()
scope.run(() => {
  const doubled = computed(() => counter.value * 2)

  watch(doubled, () => console.log(doubled.value))

  watchEffect(() => console.log('Count: ', doubled.value))
})

// to dispose all effects in the scope
scope.stop()


function getCurrentScope(): EffectScope | undefined

function onScopeDispose(fn: () => void): void

6. Some attribute usage changes

(1) useContext API deprecated
Originally, the API can be used to obtain the context information of components, including the communication data and methods of parent-child components such as attrs, slots, emit and expose.
The API will be deleted after version 3.2. The data in the context will be replaced by the new useSlots and useattrs APIs.

useAttrs:

// Import useAttrs components
import { useAttrs } from "vue";
 
// Get attrs
const attrs = useAttrs();
 
// attrs is an object. Like props, you need to get the corresponding single attr through key
console.log(attrs.msg);

useSlots:

import { defineComponent, useSlots } from "vue";
 
const ChildTSX = defineComponent({
  setup() {
    // Get slot data
    const slots = useSlots();
 
    // Rendering Components 
    return () => (
      <div>
        // Render default slot
        <p>{slots.default ? slots.default() : ""}</p>
        // Render named slot
        <p>{slots.msg ? slots.msg() : ""}</p>
      </div>
    );
  },
});
 
export default ChildTSX;

defineExpose:

Use example of original exposure:

// Import useContext component
import { useContext } from "vue";
 
// Enable expose component
const { expose } = useContext();
 
// Define the data you want to provide to the parent component
const msg: string = "Hello World!";
 
// Only when the exposed data is displayed can it be obtained in the parent component
expose({
  msg,
});

Exposure through defineExpose after version 3.2

// Import defineExpose component
import { defineExpose } from "vue";
 
// Define data
const msg: string = "Hello World!";
 
// Expose to parent component
defineExpose({
  msg,
});

defineEmits:

// Import defineEmits component
import { defineEmits } from "vue";
 
// Get emit
const emit = defineEmits(["say-hi", "chang-name"]);
 
// Call emit to say hello
emit("say-hi", "Hello!");
 
// Call emit to rename
emit("chang-name", "Tom");

Add withDefaults:

import { defineProps, withDefaults } from "vue";
 
withDefaults(
  defineProps<{
    size?: number;
    labels?: string[];
  }>(),
  {
    size: 3,
    labels: () => ["default label"],
  }
);

(2) Top level await support
await can be used directly without cooperating with async. In this case, the component setup will automatically become async setup

<script setup lang="ts">
  const post = await fetch(`/api/post/1`).then((r) => r.json());
</script>

The way it is converted into a standard component is:

<script lang="ts">
  import { defineComponent, withAsyncContext } from "vue";
 
  export default defineComponent({
    async setup() {
      const post = await withAsyncContext(
        fetch(`/api/post/1`).then((r) => r.json())
      );
 
      return {
        post,
      };
    },
  });
</script>

Topics: Front-end html server