LifeCycle Hooks

In the new version of the lifecycle functions, they can be imported into components on demand and can only be used in setup() functions.

import { onMounted, onUnmounted } from 'vue'; export default { setup () { onMounted(()=>{ // }); onUnmounted(()=> { // }); }};Copy the code

Life cycle 2. mapping between X and Composition

  • beforeCreate -> use setup()

  • created -> use setup()

  • beforeMount -> onBeforeMount

  • mounted -> onMounted

  • beforeUpdate -> onBeforeUpdate

  • updated -> onUpdated

  • beforeDestroy -> onBeforeUnmount

  • destroyed -> onUnmounted

  • errorCaptured -> onErrorCaptured

setup

understand

The setup() function is a special new method in VUe3 that can be understood as an entry point to the Composition Api.

Execution time

Execute after beforecreate and beforecreate.

Receiving props data

export default { props: { msg: { type: String, default: () => {} } }, setup(props) { console.log(props); }}Copy the code

context:

The second argument to setup() is a context object that roughly contains these properties. Note: This is not accessible in the setup() function

const MyComponent = {
  setup(props, context) {
    context.attrs
    context.slots
    context.parent
    context.root
    context.emit
    context.refs
  }
}
Copy the code

reactive

Reactive is used to create a reactive object, equivalent to the ue. Observable of 2.x. See the demo below for details.

<template> <div> <p @click="incment()"> click Me! </p> <p> <p> {{state.addCount}} </p> </div> </template> <script> import {reactive} from 'vue'; Export default {setup () {const state = reactive({count: 0, addCount: 0}); function incment () { state.count++; state.addCount = state.count * 2; } return { state, incment }; }}; </script>Copy the code

ref

The basic grammar

The ref() function creates a responsive data object for the given value, and the return value of ref() is an object that contains only a.value attribute. Here are the basic data type creation steps.

import { ref, defineComponent } from 'vue';
export default defineComponent ({
    setup () {
        const valueNumber = ref(0);
        const valueString = ref('hello world!');
        const valueBoolean = ref(true);
        const valueNull = ref(null);
        const valueUndefined = ref(undefined);

        return {
            valueNumber,
            valueString,
            valueBoolean,
            valueNull,
            valueUndefined
        };
    }
});
Copy the code

Access the reactive data created by ref in the template

import { ref } from 'vue'; export default { setup () { const value = ref(1); return { value, msg: 'hello world! '}; }}; <template> <p> {{ value }} {{ msg }} </p> </template>Copy the code

Mount REF responsive data to Reactive

When a value created by ref() is mounted directly to Reactive (), the reactive data object is automatically expanded to its original value and can be accessed directly without requiring a. Value.

import { ref, reactive } from 'vue'; export default { setup () { const count = ref(1); const state = reactive({ count }); console.log(state.count); State.count ++; //1 can be accessed directly, without passing.value; console.log(count.value); Return {count}; }};Copy the code

The new ref overwrites the old ref, as shown in the following example:

import { ref, reactive } from 'vue';
export default {
    setup () {
        const count = ref(1);
        const state = reactive({
            count
        });
        const newCount = ref(9);

        state.count = newCount;
        state.count++;

        console.log(state.count, newCount, count);// 10  10  1

        return {
           count
        };
    }
};
Copy the code

We find that the original count value is 1, because the new newCount replaces and overwrites the previous count value.

isRef

Used to determine whether a value is an object created by ref().

import { ref, isRef } from 'vue'; export default { setup () { const count = ref(1); const unwrappend = isRef(count) ? count.value : count; return { count, unwrappend }; }};Copy the code

toRefs

The torefs() function transforms a reactive object created by Reactive () into a normal object, except that each attribute node on the object is reactive data of type REF ()

<template> <p> <! </p> </template> <script> import {ref, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive, reactive toRefs } from 'vue'; export default { setup () { const state = reactive({ count: 0, value: 'hello', }) return { ... toRefs(state) }; }}; </script>Copy the code

toRef

Concept: Create a REF object for an attribute on a source responsive object that internally operates on the same data value and is updated synchronously. Equivalent to a shallow copy of a property.

Ref: A copy of new data is operated separately and does not affect each other.

Scenario: toRef is useful when passing the REF of a prop to a composite function.

import { reactive, ref, toRef } from 'vue' export default { setup () { const m1 = reactive({ a: 1, b: 2 }) const m2 = toRef(m1, 'a'); const m3 = ref(m1.a); const update = () => { // m1.a++; // when m1 changes, m2 also changes // m2.value++; // m1 changes when m2 changes m3.value++; } return {m1, m2, m3, update}}}Copy the code

computed

Computed () is used to create computed properties, and the return value is an instance of ref.

Create a read-only compute property

import { ref, computed } from 'vue'; export default { setup () { const count = ref(0); const double = computed(()=> count.value + 1); //1 double++; //Error: "double" is read-only return { count, double }; }};Copy the code

Create computable properties that are readable and writable

During the use of computed functions, passing in an object containing the get and set functions yields a readable and writable computed property

// Create a const count = ref(1) // Create a computed property const plusOne = computed({get: () => count. Value + 1, // set: Val => {count. Value = val - 1}}) The count value is updated console.log(count.value) // to print 8Copy the code

watch

The watch() function is used to monitor changes in certain data items to trigger specific actions. In this case, it listens for changes in count in real time. Check out the official documentation API

import { ref, watch } from 'vue';
export default {
    setup () {
        const count = ref(1);

        watch(()=>{
            console.log(count.value, 'value');
        })

        setInterval(()=>{
            count.value++;
        },1000);
        return {
           count,
        };
    }
};
Copy the code

Listens for the specified data source

Monitor data changes to Reactive

import { watch, reactive } from 'vue'; export default { setup () { const state = reactive({ count: 0 }) watch(()=>state.count,(count, prevCount)=>{ console.log(count, prevCount); }) setInterval(()=>{state.count++; }, 1000); return { state }; }};Copy the code

Listen for data changes of type REF

import { ref, watch } from 'vue'; export default { setup () { const count = ref(0); watch(count,(count, prevCount)=>{ console.log(count, prevCount); }) setInterval(()=>{count.value++; }, 1000); return { count }; }};Copy the code

Listens for multiple specified data changes

Monitor changes in data of the Reactive type

import { watch, reactive } from 'vue';
export default {
    setup () {
        const state = reactive({
            count: 0,
            msg: 'hello'
        })

        watch([()=> state.count, ()=> state.msg],([count, msg], [prevCount, prevMsg])=>{
            console.log(count, msg);
            console.log('---------------------');
            console.log(prevCount, prevMsg);
        })

        setTimeout(()=>{
            state.count++;
            state.msg = 'hello world';
        },1000);

        return {
           state
        };
    }
};
Copy the code

Listen for ref type data changes

import { ref, watch } from 'vue';
export default {
    setup () {
       const count = ref(0);
       const msg = ref('hello');

        watch([count, msg],([count, name], [prevCount, prevname])=>{
            console.log(count, name);
            console.log('---------------------');
            console.log(prevCount, prevname);
        })

        setTimeout(()=>{
            count.value++;
            msg.value = 'hello world';
        },1000);

        return {
           count,
           msg
        };
    }
};
Copy the code

Removal of monitoring

Watch monitoring, created within the setup() function, stops automatically when the current component is destroyed. If you want to explicitly stop a monitoring, you can simply call the return value of the watch() function

Const stop = watch(() => {/*... */}) // Call the stop function to clear the corresponding monitor stop()Copy the code

Clear invalid asynchronous tasks

The cleanup registrator function is provided in the watch callback function when the value monitored by watch() changes and we expect to cleanup invalid asynchronous tasks

  • scenario

  • Watch is repeated

  • Watch forced stop()

watchEffect

New API in vue3 for attribute listening.

How is it different from the Watch?

  • WatchEffect does not need to specify listening properties and can automatically collect dependencies. As long as responsive properties are referenced in the callback, the callback will be executed when these properties change, while watch can only listen on the specified properties and make changes (V3 can listen on multiple properties at the same time).

  • Watch gets new and old values, but watchEffect does not

  • WatchEffect performs a callback on component initialization similar to computed, but only after a dependency change is collected, which is not required by Watch unless specified parameters are set.

Basic usage

import { watchEffect, ref } from 'vue' setup () { const userID = ref(0) watchEffect(() => console.log(userID)) setTimeout(() => { userID.value  = 1 }, 1000) /* * LOG * 0 * 1 */ return { userID } }Copy the code

Stop listening

If watchEffect is registered with setup or lifecycle, it will stop automatically when unhung.

Const stop = watchEffect(() => {/*... */ }) // later stop()Copy the code

Disable side effect

What is Side effect? An unpredictable interface request is a Side effect. Let’s say we’re looking for details about a user using a user ID, and then we listen for that user ID, and when the user ID changes we make a request. You can do that with the Watch. But if our user ID changes multiple times in the process of requesting data, we will make multiple requests, and the last one will overwrite all the user details we previously returned. Not only is this a waste of resources, but there is no guarantee of the order in which watch callbacks are executed. With watchEffect we can do just that.

The callback passed in by onInvalidate(fn) is executed when watchEffect is restarted or stopped.

WatchEffect (() => {// Asynchronous API call, Const apiCall = someAsyncMethod(props. UserID) onInvalidate(() => {// Cancel the async API call. apiCall.cancel() }) })Copy the code

shallowReactive

Concept: Only responsivity (shallow responsivity) of the outermost property of the object is handled, so if the outermost property changes, the view is updated, and other layer properties change, the view is not updated.

Scenario: If the data structure of an object is deep, but the change is only the outermost attribute.

import { shallowReactive } from 'vue'

export default {
    setup() {
        const obj = {
            a: 1,
            first: {
                b: 2,
                second: {
                    c: 3
                }
            }
        }

        const state = shallowReactive(obj)

        function change1() {
            state.a = 7
        }

        function change2() {
            state.first.b = 8
            state.first.second.c = 9
            console.log(state);
        }

        return { state }
    }
}
Copy the code

shallowRef

Concept: Only value responses are processed, and reactive objects are not processed.

Scenario: If there is an object data, a new object replacement is generated later.

import { shallowRef } from 'vue'

export default {
    setup () {
        const m1 = shallowRef({a: 1, b: {c: 2}})

        const update = () => {
            m1.value.a += 1
        }

        return {
            m1,
            update
        }
    }
}
Copy the code

customRef

Create a custom REF with explicit control over its dependency trace and update trigger.

Scenario: Use customRef to stabilize input boxes

<template> <div> <input V-model ="keyword" placeholder=" search keywords "/> <p>{{keyword}}</p> </div> </template> <script> import { customRef } from 'vue' export default { setup () { const keyword = useDebouncedRef('', 500) console.log(keyword) return { keyword } } } function useDebouncedRef(value, delay = 200) { let timeout; Return customRef((track, trigger) => {return {get() {// tell Vue to track() return value}, Set (newValue) {clearTimeout(timeout) timeout = setTimeout(() => {value = newValue // tell Vue to trigger the interface to update trigger()}, delay) } } }) } </script>Copy the code

Custom Hook functions

Custom hooks are applied to mixin technology in VUe2.

Advantages: clearly know the source of code, easy to reuse

Example: Collect the coordinates of the page that the user clicked on

hook/useMousePosition.js

import { ref, onMounted, onUnmounted } from "vue"; Export default function useMousePosition() {const x = ref(-1); const y = ref(-1); // Function to collect click event coordinates const updatePosition = e => {x.value = e.pagex; y.value = e.pageY; }; / / mount after binding to click to monitor onMounted (() = > {document. AddEventListener (" click ", updatePosition); }); / / remove unbundling before clicking to monitor onUnmounted (() = > {document. The removeEventListener (" click ", updatePosition); }); return { x, y }; }Copy the code

The template uses hook functions

<template>
    <div>
        <p>{{ x }}</p>
        <p>{{ y }}</p>
    </div>
</template>

<script>
import useMousePosition from '@/hook/useMousePosition'
export default {
    setup () {
        const {x, y} = useMousePosition();
        return {
            x,
            y
        }
    }
}
</script>
Copy the code

Readonly and shallowReadonly

  • readonly:

  • Deep read only data

  • Gets an object (reactive or pure) or ref and returns the read-only proxy of the original proxy.

  • A read-only proxy is deep: any nested property accessed is also read-only.

  • shallowReadonly

  • Shallow read-only data

  • Create an agent that makes its own property read-only but does not perform deep read-only conversion of nested objects

  • Application Scenarios:

  • In certain cases where we may not want to update the data, we can wrap to generate a read-only proxy object to read the data without modifying or deleting it

Template refs

Ref () can also refer to elements or components on the page.

Element reference

Use the ref() function to create a DOM reference. Obtain the DOM reference in onMounted.

<template> <div> <p ref="dom">hello</p> </div> </template> <script> import { ref, onMounted } from 'vue'; export default { setup () { const dom = ref(null); OnMounted (()=> {console.log(dom.value)// Current DOM element}); return { dom } } }; </script>Copy the code

A component reference

<template> <div> <Test ref="comRef"/> </div> </template> <script> import { ref, onMounted } from 'vue'; import Test from "./test2"; export default { components: { Test }, setup () { const comRef = ref(null); onMounted(()=> { comRef.value.coun; // Get the subcomponent value comref.value.handle (); // Call the subcomponent function}) return {comRef}}; </script>Copy the code
  • test2

createComponent

This function is not necessary unless you want to integrate TypeScript’s type inference perfectly with your project development

Scenario: This function only provides type inference. It provides complete type inference for props in the setup() function.

import { createComponent } from 'vue'

export default createComponent({
  props: {
    foo: String
  },
  setup(props) {
    props.foo // <- type: string
  }
})
Copy the code

getCurrentInstance

Description: We can get an instance of the current component and then get the current context through the CTX property, so we can use router and vuex in steup.

<script> import {getCurrentInstance} from 'vue' export default {setup () {//getCurrentInstance CTX is equivalent to Vue2's this, // But special attention should be paid to the fact that CTX replaces this only in the development stage, and it will be wrong when you run it on the server. Const {props, proxy, Emit} = getCurrentInstance () to the console. The log (value) proxy. $router. CurrentRoute. / / / / the current path with this before things getting prototype of / / proxy. $parent $store VueX // ts (proxy as any)}} </script>Copy the code

Teleport

Description: The portal component provides a concise way to specify the parent element of the content in it, allowing us to control which parent node in the DOM renders the HTML for the nested content of ‘Teleport’ without resorting to global state or splitting into two components.

  • To String Mandatory attribute

  • to=”#last”

  • to=”.last”

  • to=”[data-teleport]”

  • Disabled Boolean Indicates the optional attribute

  • The function used to disable teleport means that the contents of the slot will not be moved to any location, but rendered at the location specified by the parent component.

    .model { position: absolute; left: 0; top: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, .3); display: flex; align-items: center; justify-content: center; } .model-body { width: 300px; height: 250px; background: #fff; }

With the ‘Teleport’ component, the props’ to ‘property specifies that the rendering position of the component is under the body, but the state of the component’ modelOpen ‘is controlled by the vUE internal component.

Fragments

Description: Fragments, one of vue3’s new features, allow a component to have multiple root nodes.

<template> <header>... </header> <main v-bind="$attrs">... </main> <footer>... </footer> </template>Copy the code