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