📜 ⬆️ ⬇️

Review Vue.js 2.6

Hi, Habr!

A new version of Vue.js - 2.6 should be released very soon. Under the cat you will find an overview of the new features of the next version, including the new syntax of slots, Vue.observable () and much more!


1. New syntax for scoped slots


This is one of the most significant changes. It includes:


The easiest way to understand this is by example:

How scoped slots were used in version Vue@2.5.22:

<template> <TestComponent> <!-- Дефолтный scoped slot --> <div slot-scope="{ message }"> {{ `Default slot with message: ${message}` }} </div> <!-- Именованный scoped slot --> <div slot="text" slot-scope="{ text }"> {{ `Named slot with text: ${text}` }} </div> </TestComponent> </template> 

How can now:

 <template> <TestComponent> <!-- Дефолтный scoped slot --> <template v-slot="{ message }"> <div> {{ `Default slot with message: ${message}` }} </div> </template> <!-- Именованный scoped slot --> <template v-slot:text="{ text }"> <div> {{ `Named slot with text: ${text}` }} </div> </template> </TestComponent> </template> 

For the default slot, you can use special syntax if named slots are not used:

 <template> <!-- v-slot используется прямо на родителе --> <TestComponent v-slot="{ message }"> <div> {{ `Default slot with message: ${message}` }} </div> </TestComponent> </template> 

And here is the abbreviation for named slots:

 <template> <TestComponent> <!-- # - это сокращение для v-slot: --> <template #text="{ text }"> <div> {{ `Named slot with text: ${text}` }} </div> </template> </TestComponent> </template> 

The new directive can be used without any scope-variables, but then the slot will still fall into the $ scopedSlots of the parent.

References:

  1. New v-slot syntax

  2. Abbreviation for v-slot


2. Dynamic argument directive


If you want a dynamic argument for v-bind or v-on, then at Vue@2.5.22 you have only one option:

 <div v-bind="{ [key]: value }"></div> <div v-on="{ [event]: handler }"></div> 

But he has a couple of drawbacks:


To get rid of them, Vue@2.6.0 introduces a new syntax:

 <div v-bind:[key]="value"></div> <div v-on:[event]="handler"></div> 

Examples of using:

 <template> <div> <!-- v-bind с динамическим ключом --> <div v-bind:[key]="value"></div> <!-- сокращение v-bind с динамическим ключом --> <div :[key]="value"></div> <!-- v-on с динамическим событием --> <div v-on:[event]="handler"></div> <!-- сокращение v-on с динамическим событием --> <div @[event]="handler"></div> <!-- v-slot с динамическим именем --> <TestComponent> <template v-slot:[name]> Hello </template> </TestComponent> <!-- сокращение v-slot с динамическим именем --> <TestComponent> <template #[name]> Cool slot </template> </TestComponent> </div> </template> 

References:


3. Creating reactive objects using Vue.observable ()


Previously, to create a reactive object, you had to shove it inside the vue component instance. Now we have a separate method that makes the object reactive - Vue.observable ().

The reactive object can be safely used in the render and computed functions.

Usage example:

 import Vue from vue; const state = Vue.observable({ counter: 0, }); export default { render() { return ( <div> {state.counter} <button v-on:click={() => { state.counter++; }}> Increment counter </button> </div> ); }, }; 

4. Download data on the server


In the new update, vue-server-renderer has changed the data loading strategy for SSR.

Previously, we were advised to call asyncData () methods on components received via router.getMatchedComponents ().

The new version has a special method for components - serverPrefetch (). vue-server-renderer will call it on each component and wait for the solution of the returned promises:

 <template> <div v-if="item"> {{ item.name }} </div> </template> <script> export default { // Вызовется на сервере async serverPrefetch() { await this.fetchItem(); }, computed: { item() { return this.$store.state.item; }, }, // Вызовется на клиенте mounted() { if (!this.item) { this.fetchItem(); } }, methods: { async fetchItem() { await this.$store.dispatch('fetchItem'); }, }, }; </script> 

To find out when the wait for all serverPrefetch () has completed and the application has completed its rendering, in the context of the server render function, you can add a rendered () hook:

 /* Упрощенный entry-server.js */ import { createApp } from './app'; export default context => new Promise((resolve, reject) => { const { app, router, store } = createApp(); const { url } = context; router.push(url); router.onReady(() => { context.rendered = () => { // Передаем состояние хранилища после завершения всех serverPrefetch() context.state = store.state; }; resolve(app); }, reject); }); 

5. Improved compiler error output


When compiling html in the render function, the vue-template-compiler may generate errors. Previously, Vue would display a description of the error without its location, now the new version will show where it is located.

Example:

 <template> <div> <template key="test-key"> {{ message }} </template> </div> </template> 

Error vue-template-compiler@2.5.22:

  Error compiling template: <div> <template key="test-key"> {{ message }} </template> </div> - <template> cannot be keyed. Place the key on real elements instead. 

New error output vue-template-compiler@2.6.0:

  Errors compiling template: <template> cannot be keyed. Place the key on real elements instead. 1 | 2 | <div> 3 | <template key="test-key"> | ^^^^^^^^^^^^^^ 4 | {{ message }} 5 | </template> 

6. Catching asynchronous errors


Now Vue can even catch asynchronous errors in lifecycle hooks and event handlers.

Example:

 /* TestComponent.vue */ <template> <div @click="doSomething()"> Some message </div> </template> <script> export default { methods: { async doSomething() { await this.$nextTick(); throw new Error('Another Error'); }, }, async mounted() { await this.$nextTick(); throw new Error('Some Error'); }, }; </script> 

Error after mount:

 [Vue warn]: Error in mounted hook (Promise/async): "Error: Some Error" 

Error after click:

 [Vue warn]: Error in v-on handler (Promise/async): "Error: Another Error" 

7. New build for ESM browsers


In the new version one more assembly Vue has been added - vue.esm.browser.js. It is designed for browsers that support ES6 Modules.

Its features:


Usage example:

 <html lang="en"> <head> <title>Document</title> </head> <body> <div id="app"> {{ message }} </div> <script type="module"> // Раньше приходилось использовать vue.esm.js, // который содержал транспилированный код, // весил чуть больше и работал чуть медленнее import Vue from 'path/to/vue.esm.browser.js'; new Vue({ el: '#app', data() { return { message: 'Hello World!', }; }, }); </script> </body> </html> 

To be honest, I would like to see another build - the same as vue.esm.browser.js, but without the HTML compiler. Then I would be able to bring more recent code to browsers with ES6 Modules when I compile templates during build.

8. Short for v-bind.prop


The v-bind directive has a special modifier - .prop. You can see what he does here in the documentation . I myself have never used it and can not imagine a case when it should be applied.

There is now a special abbreviation for it: instead of writing v-bind: someProperty.prop = “foo” you can write .someProperty = “foo”.

Example:

As it was at Vue@2.5.22:

 <template> <div> <div v-bind:textContent.prop="'Important text content'" /> <!-- Или сокращенный вариант --> <div :textContent.prop="'Important text content'" /> </div> </template> 

How can Vue@2.6.0:

 <template> <div .textContent="'Important text content'" /> </template> 

9. Support custom toString ()


Everything is simple: if you override an object's toString () method, then Vue will use it instead of JSON.stringify () when displayed.

Example:

 /* TestComponent.vue */ <template> <div> {{ message }} </div> </template> <script> export default { data() { return { message: { value: 'qwerty', toString() { return 'Hello Habr!'; }, }, }; }, }; </script> 

In the version Vue@2.5.22 we will see on the screen:

 { "value": "qwerty" } 

In version Vue@2.6.0:

 Hello Habr! 

10. Work v-for with iterated objects


In the new version, v-for can work with any objects that implement the iterable protocol , for example, Map or Set. True, for Map and Set in version 2.X, reactivity will not be supported.

Example:

 /* TestComponent.vue */ <template> <div> <div v-for="item in items" :key="item" > {{ item }} </div> </div> </template> <script> export default { data() { return { items: new Set([4, 2, 6]), }; }, }; </script> 


You can see all the new chips right now by installing the Vue beta version:
 npm i vue@2.6.0-beta.3 

If you compile vue files when building or use SSR, do not forget to add the same version of vue-template-compiler and vue-server-renderer:
 npm i vue-template-compiler@2.6.0-beta.3 vue-server-renderer@2.6.0-beta.3 


Update: Vue 2.6 was released officially, here you can read the post of Evan.

Thank you for reading the article to the end!

Source: https://habr.com/ru/post/437582/