setup

The setup function is an entry function for Vue 3.

parameter

When you use the setup function, it takes two arguments:

  1. props
  2. context

Let’s take a closer look at how each parameter is used.

Props

The first argument in the setup function is props. As expected in a standard component, the props in the setup function are reactive and will be updated when a new prop is passed in. SRC/templatem.vue:

<template>

  <div class="template-m-wrap">

    counter ---> {{ counter }}

  </div>


</template>

<script>

import { defineComponent, ref } from 'vue'

export default defineComponent({

  name: 'TemplateM',

  props: {

    test: {

      type: Object,

      default: () => {

        return {

          name: 'haha',

        }

      },

    },

  },

  setup(props) {

    const counter = ref(0)

    console.log('props===>', props)



    return {

      counter,

    }

  },

})

</
script>

Copy the code

However, because props are reactive, you can’t use ES6 deconstruction because it eliminates the responsiveness of prop.

Let’s try deconstructing props in ES6 to see what happens:

<template>

  <div class="template-m-wrap">

    counter ---> {{ counter }}

    <br/>

    test.name ---> {{ test.name }}

    <br/>

    name ---> {{ name }}

  </div>


</template>

<script>

import { defineComponent, ref } from 'vue'

export default defineComponent({

  name: 'TemplateM',

  props: {

    test: {

      type: Object,

      default: () => {

        return {

          name: 'haha',

        }

      },

    },

  },

  setup(props) {

    const counter = ref(0)

    console.log('props===>', props)

    const {name} = props.test

    return {

      counter,

      name

    }

  },

})

</
script>

Copy the code

We see that the console is starting to alert:


If you need to deconstruct a prop, you can do so safely by using toRefs in the Setup function.

<template>

  <div class="template-m-wrap">

    counter ---> {{ counter }}

    <br/>

    test.name ---> {{ test.name }}

    <br/>

    name ---> {{ name }}

  </div>


</template>

<script>

import { defineComponent, ref, toRefs } from 'vue'

export default defineComponent({

  name: 'TemplateM',

  props: {

    test: {

      type: Object,

      default: () => {

        return {

          name: 'haha',

        }

      },

    },

  },

  setup(props) {

    const counter = ref(0)

    console.log('props===>', props)

    const {name} = toRefs(props.test)

    return {

      counter,

      name

    }

  },

})

</
script>

Copy the code

This time we can see the effect as follows:


context

The second argument passed to the setup function is context. Context is a plain JavaScript object that exposes the properties of three components:

<template>

  <div class="template-m-wrap">

  </div>


</template>

<script>

import { defineComponent } from 'vue'

export default defineComponent({

  name: 'TemplateM',

  props: {

    test: {

      type: Object,

      default: () => {

        return {

          name: 'haha',

        }

      },

    },

  },

  setup(props, context) {

    console.log('props===>', props, context)

    return {

    }

  },

})

</
script>

Copy the code

We can see the effect as follows:


Context is a normal JavaScript object, that is, it is not reactive, which means you can safely use ES6 deconstruction of the context.

setup(props, { attrs, slots, emit }) {

.

}

Copy the code

Pay attention to

Attrs and slots are stateful objects that are always updated as the component itself is updated. This means you should avoid deconstructing them and always refer to properties as attrs.x or slots.x. Note that, unlike props, attrs and slots are non-reactive. If you are going to change application side effects based on attrs or slots, you should do so in the onUpdated lifecycle hook.

Access the component’s property

When SETUP is executed, the component instance has not yet been created. Therefore, you can only access the following property:

  • props
  • attrs
  • slots
  • emit

In other words, you will not have access to the following component options:

  • data
  • computed
  • methods

Use with templates

If setup returns an object, the object’s property can be accessed in the component’s template like the props property passed to Setup:

<template>

  <div class="template-m-wrap" title="hhhhh">

    <div>{{ readersNumber }} {{ book.title }}</div>

  </div>


</template>

<script>

import { defineComponent, ref, reactive } from 'vue'

export default defineComponent({

  name: 'TemplateM',

  setup() {

    const readersNumber = ref(0)

    const book = reactive({ title: 'Vue 3 Guide' })



    /
/ expose to template

    return {

      readersNumber,

      book,

    }

  },

})

</
script>

Copy the code

We can see the effect as follows:


Note that refs returned from setup are automatically unwrapped when accessed in the template, so.value should not be used in the template.

Using render functions

Setup can also return a render function that directly uses reactive state declared in the same scope:

<template>

  <div class="template-m-wrap" title="hhhhh">

  </div>


</template>

<script>

import { defineComponent, ref, reactive, h } from 'vue'

export default defineComponent({

  name: 'TemplateM',

  setup() {

    const readersNumber = ref(0)

    const book = reactive({ title: 'Vue 3 Guide' })



    /
/ expose to template

    return () => h('div', [readersNumber.value, book.title])

  },

})

</
script>

Copy the code

The effect is as follows:


usethis

Inside setup(), this will not be a reference to the active instance, because setup() is called before parsing the other component options, so this inside setup() behaves completely differently than this in the other options. This can cause confusion when using setup() with other optional apis.