After many iterations, Vue 3.0 has been released in 2020-09-18, bringing huge changes to Typescript, a massive refactoring of the Composition API, and a new RFC version of Vue. You can customize your hooks to make users more flexible. Next, we summarize some of the new features vue 3.0 brings.

  1. setup()
  2. ref()
  3. reactive()
  4. isRef()
  5. toRefs()
  6. computed()
  7. watch()
  8. LifeCycle Hooks
  9. Template refs
  10. globalProperties
  11. Suspense

Comparison of Vue2 and Vue3

  • Not friendly to TypeScript support (all attributes are placed on this object, making it hard to push component data types)
  • A large number of apis were mounted on the prototype of Vue objects, making TreeShaking difficult to implement.
  • Architecturally unfriendly support for cross-platform DOM rendering development
  • CompositionAPI. Inspired by ReactHook
  • More convenient support for JSX
  • Vue 3’s Template supports multiple root tags, Vue 2 does not
  • The virtual DOM has been rewritten, the template compilation has been optimized operation…

The setup function

The setup() function is a new attribute in VUe3 that is specifically provided for components. It provides a unified entry point for using vue3’s Composition API features. Setup functions are executed before beforeCreate and Created, which vue3 also removes. This function is equivalent to a life cycle function. Data, methods and watch in vUE are all written in the setup() function with corresponding new API

setup(props, context) {
    context.attrs
    context.slots
    context.emit
    
    return{}}Copy the code
  • Props: Used to receive props data
  • Context is used to define the context. The context object contains some useful properties that can be accessed through this in vue 2.x. This cannot be accessed through setup(), which is undefined
  • Return value: return {}, which returns reactive data, the function used in the template

Reactive functions

Reactive () takes in a normal object and returns a reactive data object. It is easy to use the created reactive data by returning it from setup and calling it directly from 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

Ref () function

The ref() function is used to create a responsive data object based on the given value. The return value of the ref() call is an object containing only one value attribute

<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)
    // To get a value defined in ref in js, use the value attribute
    console.log(count.value);
    return {
       count
    }
   }
});
</script>
Copy the code

Access reactive data created by a REF in a Reactive object

<template>
    <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: 100,
      count
    })
    // The.value attribute is not required to obtain the value of ref by reactive
    console.log(obj.count);
    return {
       ...toRefs(obj)
    }
   }
});
</script>
Copy the code

IsRef ()

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

The toRefs() function

The toRefs() function transforms a reactive object created by Reactive () into a normal object, but each attribute node on that 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 computed properties and, as in the past, returns a ref object. It can pass methods, or an object containing 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)

    // Based on the value of age, create a reactive calculation property readOnlyAge that automatically evaluates and returns a new ref based on the dependent ref
    const readOnlyAge = computed(() = > age.value++) / / 19

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

6.2 Using set() and get() methods to create a computable property that can be read and written

<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
    })
    // Assigning a value to a calculated attribute triggers the set function, which updates the age value
    age.value = 100
    return {
      age,
      computedAge
    }
  }
});
</script>
Copy the code

The watch() function

The watch function listens for a specific data source and performs side effects in the callback function. The default is lazy, meaning that callbacks are executed only when the source data being listened for changes.

7.1 Listen to data sources 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); / / 10})// When the age is changed, the watch callback is triggered to print the values before and after the change
    state.age = 100
    return {
      ...toRefs(state)
    }
  }
});
</script>
Copy the code

7.2 Listening on 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)); / / 100
    
    // Changing age triggers the watch callback to print the changed value
    age.value = 100
    return {
      age
    }
  }
});
</script>
Copy the code

7.3 Monitoring Multiple Values at the same time

<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); })// When the age is changed, the watch callback will be triggered and the values before and after the change will be printed. Note that the watch callback will be executed when either value is changed
    state.age = 100
    state.name = 'vue3'
    return {
      ...toRefs(state)
    }
  }
});
</script>

Copy the code

7.4 stop Stops listening

Watch monitoring, created within the setup() function, stops automatically when the current component is destroyed. If you want to explicitly stop a watch, you can call the return value of the watch() function, with the 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 the age is changed, the watch callback will be triggered and the values before and after the change will be printed. Note that the watch callback will be executed when either value is changed
    state.age = 100
    state.name = 'vue3'

    setTimeout(() = > { 
      stop()
      // The watch callback will not be triggered
      state.age = 1000
      state.name = 'vue3-'
    }, 1000) // Cancel the watch after 1 second
    
    return {
      ...toRefs(state)
    }
  }
});
</script>
Copy the code

In the later period of life.

A new version of the lifecycle function, which can be imported into the component on demand and can only be used in the setup() function, but can also be defined outside of setup and used in 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 in a template, declare a ref in setup() and return it as usual

  1. As usual, write the name of ref in the HTML
  2. Define a ref in steUP
  3. Steup returns an instance of ref
  4. OnMounted can be used to obtain the RefImpl object of ref. Value can be used to obtain the real DOM
<template> <! Step 1: Write the name of ref in the HTML 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) {
    // Get the real DOM
    const elmRefs = ref<null | HTMLElement>(null);
    onMounted (() = > {
      console.log(elmRefs.value); // Get a RefImpl object and access the data via.value
    })

    return {
      elmRefs
    }
  }
});
</script>
Copy the code

X. Global configuration of VUE

Objects that contain the global configuration of the VUE application, configured through config on the VUE instance. You can modify the properties listed below before mounting the application:

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

Assign handlers for component rendering functionality and uncaught errors during viewing programs. The error and application instance will invoke the handler

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

Global properties that can be accessed in any component instance within the application, and the component’s properties will take precedence. This can be used instead of Vue 2. xvue. prototype extension:

const app = Vue.createApp({})

app.config.globalProperties.$http = 'xxxxxxxxs'
Copy the code

GetCurrentInstance () gets the instance of the current component, and then gets the current context from the CTX property. This allows us to use router and vuex in setup, which allows us to manipulate variables, global properties, component properties, and so on

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

Suspense Components

Suspense components for React before we start with Suspense components for Vue, it’s worth taking a look at Suspense components for React, because they function similarly.

React.lazy accepts a function that calls import() dynamically. It must return a Promise that needs to resolve 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 react. lazy-like defineAsyncComponent function to handle dynamic import. DefineAsyncComponent can accept a factory function that returns a promise. Promise’s resolution callback should be invoked when you retrieve the component definition from the server. 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.component('async-component', AsyncComp)
Copy the code

Suspense component has also been added to Vue3:

<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 list" :key="item.id">{{item.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 registration}, emits: ["emits-name"], // Setup (props, Context) {console.log(props. Name) console.log(props. List) const state = reactive<IState>({name: 'vue 3.0 ', count: 0, list: [ { name: 'vue', id: 1 }, { name: 'vuex', id: 2}]}) const a = computed(() => state.name) onMounted(() => {}) function handleClick () {state.count ++ // Invoke methods of the parent component context.emit('emits-name', state.count) } return { ... toRefs(state), handleClick } } }); </script>Copy the code

Vue 3 ecology

  • website
  • The source code
  • Vite builder
  • Scaffolding:cli.vuejs.org/
  • vue-router-next
  • vuex4.0

The UI component library

  • vant2.x

  • Ant Design of Vue 2.x

  • element-plus