vue.js basic learning (basic use of composite API: setup())

Basic introduction: Vue JS composite API: setup() basic use

1. Using watch in setup

  • watch(): listen to one or more responsive data sources and call the given callback function when the data source changes.
  • Details: watch() is lazy listening by default, that is, the callback function is executed only when the listening source changes. The first parameter is the source of the listener. Watch (listening responsive reference, callback function). This source can be the following:
    • A function that returns a value
    • A ref
    • A responsive object
    • ... or an array of values of the above type
    • The second parameter is the callback function to call when the change occurs. This callback function takes three parameters: the new value, the old value, and a callback function for registering side-effect cleanup. This callback function will be called before the next re execution of the side effects. It can be used to clear the invalid side effects, such as asynchronous requests waiting.

      When listening to multiple sources, the callback function accepts two arrays, corresponding to the new value and the old value in the source array.

      The third optional parameter is an object, which supports the following options:

    • immediate: trigger the callback immediately when the listener is created. The old value at the first call is undefined.
    • Deep: if the source is an object, force a deep traversal to trigger a callback when a deep level change occurs. reference resources Deep listener.
    • flush: adjust the refresh timing of the callback function. reference resources Refresh timing of callback and watchEffect().
    • onTrack / onTrigger: debug listener dependencies. reference resources Debug listener.
  • watchEffect(): run a function immediately, track its dependencies responsively, and re execute when the dependencies change.  
    • The first parameter is the side-effect function to run. The parameter of this side-effect function is also a function used to register the cleanup callback. The cleanup callback will be called before the next execution of this side effect, and can be used to clean up invalid side effects, such as waiting asynchronous requests (see the following example).

    • The second parameter is an optional option, which can be used to adjust the refresh timing of side effects or debug the dependency of side effects.

      By default, the listener executes before the component is rendered. Setting flush: 'post' will cause the listener to delay execution until the component is rendered. See Trigger timing of callback . In some special cases (for example, to invalidate the cache), it may be necessary to trigger the listener immediately when the responsive dependency changes. This can be achieved by setting flush: 'sync'. However, this setting should be used with caution, because if multiple attributes are updated at the same time, it will cause some performance and data consistency problems.

    • The return value is a function used to stop the side effect.

  • Difference between watch() and watchEffect():
    • watchEffect() does not need to specify the listening properties, and automatically collects dependencies. As long as the responsive properties are referenced in the callback, the callback will execute as long as these properties change; watch() can only listen to the specified attributes and make the execution of callback functions. It can listen to multiple from vue3.

    • watch() can get new and old values, but watchEffect() cannot.

    • watchEffect() is executed once when the component is initialized to collect dependencies. watch() does not need to be specified at the beginning.  

Source code:

<script>
  import Hello from './components/Hello.vue';
  import { ref,reactive, toRefs, watch, watchEffect,} from 'vue';//ref defines a reactive variable, and reactive can define a reference data type
  export default{
    data(){
      return{
        message:'hello word!'
      }
    },
    setup(){
      //counter logic code
      const counter=ref(0)
      function changCoun(){
        counter.value++
      }
      //Watch (listening responsive reference, callback function)
      watch(counter,(newVal,oldVal)=>{
        console.log("newVal----",newVal);
        console.log("oldVal----",oldVal);
      })

      //use logic code
      const use=reactive({
        name:'xueysr',
        age:18
      })
      function changeName(){
        use.name='x-ysr'
      }
      // watch(use,(newVal,oldVal)=>{
      //   console.log("newVal---",newVal);
      //   console.log("oldVal---",oldVal)
      // })
      //Watcheffect (callback function), it is not necessary to specify the listening property, and the dependency is automatically collected
      watchEffect(()=>{
        console.log(use.name)
      })
      /*
      watch()Difference from watchEffect()
      1,watchEffect()There is no need to specify the listening properties and automatically collect dependencies. As long as the responsive properties are referenced in the callback, the callback will execute as long as these properties change
      watch()You can only listen to the specified attributes and make the execution of callback functions. You can listen to multiple from vue3.
      2,watch()New and old values can be obtained, but watchEffect() cannot.
      3,watchEffect()When the component is initialized, it will be executed once to collect dependencies. watch() is not required. It is specified at the beginning.
      */

      return{
        counter,
        use,
        changCoun,
        changeName
      }
    },
    //Optional API
    watch:{
      message:function(newVal,oldVal){

      }
    },
    components:{
      Hello
    }
  }

</script>

<template>
  <h2>{{counter}}</h2>
  <h2>{{use.name}}</h2>
  <button @click="changCoun">change counter</button>
  <button @click="changeName">Change name</button>
  <Hello></Hello>
</template>

<style>

</style>

2. The life cycle hook function is used in setup

  • onMounted(): register a callback function and execute it after the component is mounted.

  • onUpdated(): register a callback function and call it after the component updates its DOM tree due to a responsive state change.

  • onUnmounted(): register a callback function and call it after the component instance is unloaded.

  • onBeforeMount(): register a hook, which is called before the component is mounted.

  • onBeforeUpdate(): register a hook and call it before the component updates its DOM tree due to a responsive state change.

  • onBeforeUnmount(): register a hook and call it before the component instance is unloaded.

  • onErrorCaptured(): register a hook and call it when the error passed by the descendant component is captured.

  • onRenderTracked() registers a debugging hook, which is called when the component traces a responsive dependency during rendering. This hook is only available in development mode and will not be called during server-side rendering.

  • Onrendertrigged(): register a debugging hook, which is called when the component rendering is triggered by the change of the responsive dependency. This hook is only available in development mode and will not be called during server-side rendering.

  • onActivated(): register a callback function. If the component instance is part of the < keepalive > cache tree, it will be called when the component is inserted into the DOM. This hook is not called during server-side rendering.

  • onDeactivated(): register a callback function. If the component instance is part of the < keepalive > cache tree, it will be called when the component is removed from the DOM. This hook is not called during server-side rendering.

  • onServerPrefetch(): register an asynchronous function, which is called before the component instance is rendered on the server.

Source code:

<script>
  import Hello from './components/Hello.vue';
  import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated} from 'vue';
  export default{
    data(){
      return{
        message:'hello word!'
      }
    },
    setup(){
      //Life cycle hook function with one parameter and one callback function
      onBeforeMount(()=>{
        console.log('onBeforeMount')
      });
      onMounted(()=>{
        console.log('onMounted')
      });
      onBeforeUpdate(()=>{
        console.log('onBeforeUpdate')
      });
      onUpdated(()=>{
        console.log(' onUpdated')
      })
    }
  }

</script>

<template>
  
</template>

<style>

</style>

3. Use computed in setup

  • computed(): accepts a getter function and returns a read-only responsive ref object. This ref exposes the return value of the getter function through. Value. It can also accept an object with get and set functions to create a writable ref object.

Source code:

<script>
  import Hello from './components/Hello.vue';
  import { ref,reactive, toRefs, watch, watchEffect, computed} from 'vue';//ref defines a reactive variable, and reactive can define a reference data type
  export default{
    data(){
      return{
        message:'hello word!'
      }
    },
    setup(){
      //msg logic code
      const msg=ref('hello word!')
      const reverseMsg=computed(()=>{//Returns an object with a value attribute
        return msg.value.split('').reverse().join('')
      })
      console.log(reverseMsg.value)
      return{
       msg,
       use
      }
    },
    //Optional API
    //  computed:{
    //   reverseMsg:function(){
    //     return this.message.split('').reverse().join('')
    //   }
    //  }
  }

</script>

<template>
  <h2>{{msg}}</h2>
</template>

<style>

</style>

4. Using props in setup

  • The first parameter of the setup function is the props of the component. Consistent with standard components, the props of a setup function are responsive and will be updated synchronously when new props are passed in.

  • If you really need to deconstruct props objects, or if you need to pass a props to an external function and maintain responsiveness, you can use toRefs() and toRef() These two utility functions.

Source code:

<!-- App.vue -->
<script>
  import Hello from './components/Hello.vue';
  export default{
    data() {
        return {
            message: "hello word!"
        };
    },
    components: { Hello }
}

</script>

<template>
  <Hello :message="message"></Hello>
</template>

<style>

</style>

<!-- Hello.vue -->
<script>
  export default{
    data(){
      return{
        counter:0
      }
    },
    props:{
      message:{
        type:String,
        default:'Hello'
      }
    },
    setup(props){
      console.log(props.message)
    },
    // mounted(){
    //   console.log(this.message)
    // }
  }
</script>

<template>
  <h2>{{message}}</h2>
</template>

<style>

</style>

5. context parameter in setup

  • The second parameter passed into the setup function is a setup context object. The context object exposes some other values that may be used in setup:
  • export default {
      setup(props, context) {
        // Transparent Attributes (non responsive object, equivalent to $attrs)
        console.log(context.attrs)
    
        // Slots (non responsive objects, equivalent to $slots)
        console.log(context.slots)
    
        // Trigger event (function, equivalent to $emit)
        console.log(context.emit)
    
        // Expose public properties (functions)
        console.log(context.expose)
      }
    }
  • Attrs and slots are stateful objects that always update with the update of the component itself. This means that you should avoid deconstructing them and always pass attrs X or slots Use the attributes in the form of X. In addition, it should be noted that unlike props, the attributes of attrs and slots are not responsive.  

Source code:

<!-- App.vue -->

<script>
  import Hello from './components/Hello.vue';
  export default{
    data() {
        return {
            message: "hello word!"
        };
    },
    methods:{
      injectContext(value){
        console.log(value)
      }
    },
    mounted(){
      console.log(this.$refs.content)
      this.$refs.content.sendeParent()
    },
    components: { Hello }
}

</script>

<template>
  <!-- <Hello id="content" @injectContext="injectContext"></Hello> -->
  <Hello id="content" ref="content" @injectContext="injectContext"></Hello>
  <Hello id="content"></Hello>
  <button @click="message='Hello!'">change</button>
</template>

<style>

</style>

<!-- Hello.vue -->
<script>
  import {onUpdated,toRefs,ref,h} from 'vue'
  export default{
    data(){
      return{
        counter:0
      }
    },
    props:{
      message:{
        type:String,
        default:'Hello'
      }
    },
    setup(props,context){
      const counter=ref(20)
      function sendeParent(){
        context.emit('injectContext',counter)
      }
      console.log(context)
      context.expose({
        sendeParent,
        counter
      })
      return()=>h('div',counter.value)
      //props
      // console.log(props.message)
      // const {message}=toRefs(props)
      // console.log(message.value)
      // onUpdated(()=>{
      //   console.log(message.value)
      // })
    },
    // mounted(){
    //   console.log(this.message)
    // }
  }
</script>

<template>
  <h1>I am a subcomponent content</h1>
  <h2>{{message}}</h2>
  <button @click="sendeParent">send data</button>
</template>

<style>

</style>

6. provide and inject in setup

  • provide(): provides a value that can be injected by descendant components.

  • function provide<T>(key: InjectionKey<T> | string, value: T): void
  • provide() accepts two parameters: the first parameter is the key to be injected, which can be a string or a symbol, and the second parameter is the value to be injected.

  • When TypeScript is used, the key can be a symbol whose type is asserted as InjectionKey. InjectionKey is a tool type provided by Vue, inherited from symbol, and can be used to synchronize the types of values between provide() and inject().

  • inject(): inject a value provided by the ancestor component or the entire application (through app.provide()).

  • The first parameter is the injected key. Vue will traverse the parent component chain and determine the provided value by matching the key. If multiple components on the parent component chain provide values for the same key, the components closer to each other will "overwrite" the values provided by the components farther away in the chain. If no value can be matched through the key, inject() will return undefined unless a default value is provided.

  • The second parameter is optional, that is, the default value used when no key is matched. It can also be a factory function to return some complex values. If the default value itself is a function, you must pass false as the third parameter, indicating that the function is the default value, not a factory function.

  • Similar to the API for registering life cycle hooks, inject() must be called synchronously in the setup() phase of the component.

  • When using TypeScript, the key can be a symbol of type InjectionKey. InjectionKey is a tool type provided by Vue, inherited from symbol, and can be used to synchronize the types of values between provide() and inject().

Source code:

<!-- App.vue -->
<script>
  import Hello from './components/Hello.vue';
  import {provide} from 'vue'
import { ref } from '@vue/reactivity';
  export default{
    data() {
        return {
            
        };
    },
    setup(){
      const name=ref('xueysr')
      provide('name',name)
      function changeName(){
        name.value='x-ysr'
      }
      return{
        changeName
      }
    },
    components: { Hello }
}

</script>

<template>
  <Hello></Hello>
  <button @click="changeName">change name</button>
</template>

<style>

</style>

<!-- Hello.vue -->
<script>
  import {inject} from 'vue'
  export default{
    data(){
      return{
        counter:0
      }
    },
    setup(){
      const name=inject('name')
      return{
        name
      }
    }
  }
</script>

<template>
  <h1>I am hello assembly</h1>
  <h2>{{name}}</h2>
</template>

<style>

</style>

Part of the content is reproduced from: Composite API: setup() | Vue.js 

Posted by Addos on Thu, 25 Aug 2022 07:29:11 +0530