After a long iteration, Vue 3.0 was finally released on 2020-09-18 with radical changes, extensive refactoring with Typescript, and the RFC version of Composition API. Similar to React Hook, Vue can be customized to make users more flexible. Next, I will summarize some new features brought by Vue 3.0. Setup () ref() reactive() isRef() toRefs() computed() watch() LifeCycle Hooks(new LifeCycle) Template refs globalProperties Suspense

Vue2 vs. Vue3

  • Unfriendly to TypeScript support (all properties are placed on this object, making it difficult to push component data types)
  • TreeShaking is difficult to implement because of the large number of apis mounted on the prototype of the Vue object.
  • The architecture level is not friendly to cross-platform DOM rendering development support
  • CompositionAPI. Inspired by ReactHook
  • More convenient support for JSX
  • The Template of Vue 3 supports multiple root tags, but Vue 2 does not
  • The virtual DOM has been rewritten and the compilation of the template has been optimized.

Setup function

The setup() function is a new property provided in VUe3 specifically for components. This gives us a unified entry point to vue3’s new Composition API feature. The setup function executes after beforeCreate and before Created. Vue3 also removes both hooks. In vUE, all the data, methods, watch and other functions are written in the setup() function with the corresponding new API

  setup(props, context) {
      context.attrs
      context.slots
      context.parent
      context.root
      context.emit
      context.refs
  
   return {
  
      }
    }
Copy the code
  • Props: To receive props data
  • Context is used to define the context. Context objects contain some useful properties
  • Voo2.x requires this to be accessed. This cannot be accessed in setup(); it is undefined
  • Return value: return {}, which returns reactive data, the function that needs to be used in the template

Reactive function

The reactive() function receives a common object and returns a reactive data object. To use the reactive data created, simply create it, return it in the setup, and call it directly from the template

<template>
  {{name}} // test
<template>

<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';
export default defineComponent({
  setup(props, context) {

    let state = reactive({
      name: 'test'
    });

    return state
  }
});
</script>
Copy the code

The ref() function

The ref() function is used to create a responsive data object based on a given value. The return value of a call to ref() is an object that contains only a value attribute. Access to the ref function only within the setup function requires adding.value

<template> <div class="mine"> {{count}} // 10 </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue'; Export default defineComponent({setup() {const count = ref<number>(10), You need to use the value attribute console.log(count.value); return { count } } }); <div > <div class="mine"> {{count}} -{{t}} // 10-100 </div> </template> <script lang="ts"> import { defineComponent, reactive, ref, toRefs } from 'vue'; export default defineComponent({ setup() { const count = ref<number>(10) const obj = reactive({ t: Value attribute console.log(reactive, count); value attribute console.log(reactive, count); value attribute console.log(reactive, count); return { ... toRefs(obj) } } }); </script>Copy the code

IsRef () function

IsRef () is used to determine whether a value is an object created by ref()

<script lang="ts">
import { defineComponent, isRef, ref } from 'vue';
export default defineComponent({
  setup(props, context) {
    const name: string = 'vue'
    const age = ref<number>(18)
    console.log(isRef(age)); // true
    console.log(isRef(name)); // false

    return {
      age,
      name
    }
  }
});
</script>
Copy the code

5. ToRefs () function

The toRefs() function converts a reactive object created by reactive() into a normal object, but each attribute node on the object is reactive data of type ref()

<template> <div class="mine"> {{name}} // test {{age}} // 18 </div> </template> <script lang="ts"> import { defineComponent, reactive, ref, toRefs } from 'vue'; export default defineComponent({ setup(props, context) { let state = reactive({ name: 'test' }); const age = ref(18) return { ... toRefs(state), age } } }); </script>Copy the code

Six, the computed ()

This function is used to create the evaluated property, and as in the past, the value it returns is a ref object. It can pass methods, or an object containing the set() and get() methods

6.1 Creating read-only Computing Properties

import { computed, defineComponent, ref } from 'vue'; Export default defineComponent({setup(props, context) {const age = ref(18), Create a responsive computed property readOnlyAge, which is automatically computed based on the dependent ref and returns a new ref const readOnlyAge = computed(() => age.value++) // 19 return {age,  readOnlyAge } } }); </script>Copy the code

6.2 Create a readable and writable computing property using the set() and get() methods

<script lang="ts"> import { computed, defineComponent, ref } from 'vue'; export default defineComponent({ setup(props, context) { const age = ref<number>(18) const computedAge = computed({ get: () => age.value + 1, set: Value => age. Value + value}) Age. Value = 100 return {age, computedAge}}); </script>Copy the code

7. Watch () function

The watch function is used to listen to a specific data source and perform side effects in the callback function. The default is lazy execution, meaning that the callback is executed only when the source data being listened for has changed.

7.1 Listen to the data source declared by reactive

<script lang="ts"> import { computed, defineComponent, reactive, toRefs, watch } from 'vue'; interface Person { name: string, age: number } export default defineComponent({ setup(props, context) { const state = reactive<Person>({ name: 'vue', age: 10 }) watch( () => state.age, (age, preAge) => { console.log(age); // 100 console.log(preAge); State. Age = 100 return {... toRefs(state) } } }); </script>Copy the code

7.2 Listen for data sources declared with ref

<script lang="ts"> import { defineComponent, ref, watch } from 'vue'; interface Person { name: string, age: number } export default defineComponent({ setup(props, context) { const age = ref<number>(10); watch(age, () => console.log(age.value)); Age. Value = 100 return {age}}}); </script>Copy the code

7.3 Listening for Multiple Values

<script lang="ts"> import { computed, defineComponent, reactive, toRefs, watch } from 'vue'; interface Person { name: string, age: number } export default defineComponent({ setup(props, context) { const state = reactive<Person>({ name: 'vue', age: 10 }) watch( [() => state.age, () => state.name], ([newName, newAge], [oldName, oldAge]) => { console.log(newName); console.log(newAge); console.log(oldName); console.log(oldAge); Age = 100 state. Name = 'vue3' return {... toRefs(state) } } }); </script>Copy the code

7.4 stop Stopping the listener

The watch monitor, created in the setup() function, automatically stops when the current component is destroyed. To explicitly stop a monitor, call the return value of the watch() function with the following syntax:

<script lang="ts"> import { set } from 'lodash'; import { computed, defineComponent, reactive, toRefs, watch } from 'vue'; interface Person { name: string, age: number } export default defineComponent({ setup(props, context) { const state = reactive<Person>({ name: 'vue', age: 10 }) const stop = watch( [() => state.age, () => state.name], ([newName, newAge], [oldName, oldAge]) => { console.log(newName); console.log(newAge); console.log(oldName); console.log(oldAge); }) // When age is changed, a callback to watch is triggered, printing the values before and after the change. State. age = 100 state.name = 'vue3' setTimeout(()=> {stop() // When changing, State. age = 1000 state.name = 'vue3-'}, 1000) return {... toRefs(state) } } }); </script>Copy the code

LifeCycle Hooks(New late Life)

New lifecycle functions can be imported into components on demand and can only be used within the setup() function, but can also be defined outside of setup and used within setup

<script lang="ts"> import { set } from 'lodash'; import { defineComponent, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onErrorCaptured, onMounted, onUnmounted, onUpdated } from 'vue'; export default defineComponent({ setup(props, context) { onBeforeMount(()=> { console.log('beformounted! ') }) onMounted(() => { console.log('mounted! ') }) onBeforeUpdate(()=> { console.log('beforupdated! ') }) onUpdated(() => { console.log('updated! ') }) onBeforeUnmount(()=> { console.log('beforunmounted! ') }) onUnmounted(() => { console.log('unmounted! ') }) onErrorCaptured(()=> { console.log('errorCaptured! ') }) return {} } }); </script>Copy the code

Nine, the Template refs

To get a reference to an element or component instance inside the template, we can declare a ref in setup() and return it as usual

As usual, write the name of the ref in the HTML

Define a ref in steup

Steup returns an instance of ref

In onMounted, you can obtain the RefImpl object of ref, and you can obtain the real DOM through

<template> <! -- Step 1: As usual, <div class="mine" ref="elmRefs"> <span>1111</span> </div> </template> <script lang="ts"> import { set } from 'lodash'; import { defineComponent, onMounted, ref } from 'vue'; Export default defineComponent ({setup (props, context) {/ / to get real dom const elmRefs = ref < null | HTMLElement > (null); onMounted (() => { console.log(elmRefs.value); }) return {elmRefs}}); // Return {elmRefs}}; </script>Copy the code

Global configuration of VUE

Configured via a config on the vUE instance, an object that contains the global configuration of the VUE application. You can modify the properties listed below before mounting the application:

const app = Vue.createApp({}) app.config = {... }Copy the code

Assign handlers for uncaught errors during component rendering functions and observations. The error and the application instance invoke the handler

 app.config.errorHandler = (err, vm, info) => {}
Copy the code

Global properties that can be accessed from any component instance within the application, the component’s properties will take precedence. This can be substituted for the Vue 2.xvue.prototype extension:

const app = Vue.createApp({})
app.config.globalProperties.$http = 'xxxxxxxxs'
Copy the code

GetCurrentInstance () getCurrentInstance() getCurrentInstance() getCurrentInstance() getCurrentInstance() getCurrentInstance() This allows you to use router and vuex in setup, which allows you to manipulate variables, global properties, component properties, and so on

setup( ) {
  const { ctx } = getCurrentInstance();
  ctx.$http
}
Copy the code

Suspense component

Before getting into Vue’s Suspense components, it’s worth taking a look at the React components as they have similar features. React. Lazy accepts a function that requires a dynamic call to import(). It must return a Promise that resolves a Default export React component.

import React, { Suspense } from 'react'; const myComponent = React.lazy(() => import('./Component')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading... </div>}> <myComponent /> </Suspense> </div> ); }Copy the code

Vue3 also adds a defineAsyncComponent function like React. Lazy to handle dynamic introductions. DefineAsyncComponent can accept a factory function that returns a promise. When you retrieve the component definition from the server, the Promise’s resolution callback should be called. You can also call Reject (Reason) to indicate that the load has failed

import { defineAsyncComponent } from 'vue' const AsyncComp = defineAsyncComponent(() => Import ('. / components/AsyncComponent. Vue ')) app.com ponent (' async - component 'AsyncComp) Vue3 also adds Suspense components: <template> <Suspense> <template #default> <my-component /> </template> <template #fallback> Loading ... </template> </Suspense> </template> <script lang='ts'> import { defineComponent, defineAsyncComponent } from "vue"; const MyComponent = defineAsyncComponent(() => import('./Component')); export default defineComponent({ components: { MyComponent }, setup() { return {} } }) </script>Copy the code

Vue 3.x complete component template structure

A completed vUE 3.x complete component template structure contains: component name, props, components, setup(hooks, computed, watch, methods, etc.)

<template> <div class="mine" ref="elmRefs"> <span>{{name}}</span> <br> <span>{{count}}</span> <div> <button @ click = "handleClick" > test button < / button > < / div > < ul > < li v - for = "item in the list:" key = "item. Id" > {{item. The name}} < / li > < / ul > < / div > </template> <script lang="ts"> import { computed, defineComponent, getCurrentInstance, onMounted, PropType, reactive, ref, toRefs } from 'vue'; interface IState { count: 0, name: string, list: Array<object> } export default defineComponent({ name: 'demo', / / father component and component parameters son props: {name: {type: String as PropType < null | '>, the default:' vue3. X '}, list: {type: Array as PropType<object[]>, default: () => []}}, components: {/// TODO component register}, emits: ["emits-name"], // setup (props, Log (props. Name) console.log(props. List) const state = reactive<IState>({name: 'vue 3.0 component ', count: reactive<IState>({name: 'vue 3.0 component ', count: reactive<IState>) 0, list: [ { name: 'vue', id: 1 }, { name: 'vuex', id: 2}]}) Const A = computed(() => state.name) onMounted(() => {}) Function handleClick () {state.count ++ // Calls the parent component's method context.emit('emits-name', state.count) } return { ... toRefs(state), handleClick } } }); </script>Copy the code