In Vue3, the setup function is a newly introduced concept. It replaces the previous version of data, computed, methods and other options to set the initial state and logic of the component. The introduction of the setup function makes the logic of the component clearer and more flexible. This article will mainly introduce the basic usage of Setup and the small number of principles.
- More flexible organizational logic: The setup function can organize related logic according to functions, making components clearer and easier to maintain. No longer limited by options in the Options API, you can organize your code more freely.
- Logical multiplexing: Logic can be extracted into a reusable function and called in the setup function to achieve logical multiplexing, avoiding the problems that may arise when implementing logical multiplexing through mixins or mixed objects in the Options API.
- Better type inference: Since the setup function itself is a normal JavaScript function, it can better cooperate with TypeScript to provide better type inference and code prompts.
- Better responsive processing: The setup function can use ref, reactive and other functions to create responsive data, which can more conveniently process the status of components and realize dynamic update of data.
- Fine-grained life cycle hook: In the setup function, you can use onMounted, onUpdated, onUnmounted and other functions to register the component's life cycle hook, which can control the life cycle behavior of the component more granularly.
- Better code organization: The setup function concentrates the logic of the component in one place, making the code easier to read, easy to maintain, and allows clearer view of the overall logic of the component.
setup() function
setup()
Hooks are entrances to use a combined API in components, usually only when:
- When using a combined API in a non-single-file component.
- When integrating code based on composite APIs in components based on option APIs.
In other cases, priority should be givengrammar.
1.1 Basic use
We can useResponsive APITo declare the responsive state,setup()
Objects returned in the function are exposed to templates and component instances. Other options can also be obtained through component instancessetup()
Exposed properties.
<script> import { ref } from 'vue' export default { setup() { const count = ref(0) // The return value is exposed to templates and other option API hooks return { count } }, mounted() { () // 0 } } </script> <template> <button @click="count++">{{ count }}</button> </template>
Please note that accessing from within the templatesetup
When the ref is returned,It will automatically unpack, so you no longer have to write it for it in the template.value
. When passingthis
The same will be unpacked when accessing.
setup()
It does not contain access to component instances, that is,setup()
Visitthis
Will beundefined
. You can access the values exposed by the combination API in the option API, but the other way around is not.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CombinationAPI</title> </head> <body> <div > {{ count }} <button @click="add">add1</button> </div> </body> <script src="../lib/"></script> <script> const { ref, onMounted } = Vue ({ setup () { const count = ref(0) const add = () => { += 1 } onMounted(() => { (1111) }) return { count, add } }, data () { return { count: 10 } }, methods: { add () { += 10 } }, mounted () { ('2222') } }).mount('#app') </script> </html>
Execute first in life cycle Combined API and then execute option API, while the rest are given priority to combining APIs.
1.2 Visit Prop
setup
The first parameter of a function is the componentprops
. Consistent with standard components, onesetup
Functionalprops
is responsive and will be updated synchronously when new props are passed.
{ props: { title: String, count: Number }, setup(props) { () () } }
Please note that if you deconstruct
props
Object, deconstructed variables will lose responsiveness. Therefore we recommendto use props in the form.
If you really need to deconstructprops
Object, or you need to pass a prop to an external function and maintain responsiveness, then you can use two tool functions:
{ setup(props) { // Convert `props` into an object with all refs and deconstruct const { title } = toRefs(props) // `title` is a ref that tracks `` () // Or, convert a single property of `props` to a ref const title = toRef(props, 'title') } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>CombinationAPI</title> </head> <body> <div > <button @click="num++">add1</button> {{ num }} <my-root :num="num"></my-root> </div> </body> <script src="../lib/"></script> <template > <div>{{ num }} -- {{ test }}</div> </template> <script> const { ref, onMounted, computed } = Vue const Root = { props: ['num'], template: '#root', // setup (props) { // Never deconstruct props // ('111') // return { // test: computed(() => ) // Continue to maintain responsiveness // } // } setup ({ num }) { (num) return { test: computed(() => num) // Lost the responsiveness - the value of test will not change } } } ({ setup () { const num = ref(10000) return { num } }, components: { MyRoot: Root } }).mount('#app') </script> </html>
1.3 Setup context
Incomingsetup
The second parameter of the function is aSetup contextObject. The context object exposes some other insetup
Possible values in:
{ setup(props, context) { // Transparent Attributes (non-responsive object, equivalent to $attrs) () // Slot (non-responsive object, equivalent to $slots) () // Trigger event (function, equivalent to $emit) () // Expose public properties (functions) () } }
This context object is non-responsive and can be safely deconstructed:
{ setup(props, { attrs, slots, emit, expose }) { ... } }
attrs
andslots
They are all stateful objects, and they will always be updated as the component itself is updated. This means you should avoid deconstructing them and always passor
The form uses the properties in it. Also note that
props
different,attrs
andslots
All attributesnoResponsive. If you want to useattrs
orslots
Changes to perform side effects, then you shouldonBeforeUpdate
Write relevant logic in the life cycle hook.
expose
Functions are used to explicitly restrict the properties exposed by the component, and when the parent component accesses an instance of the component through a template reference, it will only be accessible.expose
What the function exposes
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>setupContext object</title> </head> <body> <div > <my-com ref="comref" class="myBox" style="color: red" msg="hello msg" @my-event="getData"> <template #header> header </template> <div>content</div> <template #footer> footer </template> </my-com> </div> </body> <template > <div> <h1>Subcomponents</h1> <button @click="sendData">Send data</button> <slot name="header"></slot> <slot></slot> <slot name="footer"></slot> </div> </template> <script src="../lib/"></script> <script> const { createApp, ref, onMounted } = Vue const Com = { template: '#com', setup (props, context) { // attrs Get the value passed through // slots If slots are used // emit child component passes value to parent component // expose child components expose properties and methods that can be called by the parent component --- options API ref to obtain instances of child components (props) () // ref is not included in the transmissible () const sendData = () => { // The child component passes value to the parent component ('my-event', 1000) } // Custom properties and methods for use by the parent component const a = ref(1) const b = ref(2) const c = ref(3) const fn = () => { = 100 } // The object is exposed ({ a, b, fn }) return { sendData } } } ({ setup () { const getData = (val) => { // Receive the value of the subcomponent ('666', val) } const comref = ref() // comref is ref="comref" in the template onMounted(() => { ('com', ) // {} ('a', ) // 1 ('b', ) // 2 ('c', ) // undefined because it is not exposed () ('a', ) // 100 }) return { getData, comref } }, components: { MyCom: Com } }).mount('#app') </script> </html>
In the parent component's requirement to obtain the properties and methods of the child component's instance through ref, it is necessary to pay attention to:
1. If the child component is an option API component, there is basically no need to do anything
2. If the child component is a combined API component, it is necessary to expose the properties and methods that need to be used to the parent component.
3. If the parent component uses the option API, you can access the properties and methods that the child component wants you to see through this.$
4. If the parent component uses a combination API, you need to create a refName in the setup, and then access the properties and methods that the child component wants you to see (const refName = ref() )
1.4 Use with rendering functions
setup
You can also return oneRendering functions, at this time, the responsive state declared under the same scope can be directly used in the rendering function:
{ setup() { const count = ref(0) return () => h('div', ) } }
Returning a rendering function will prevent us from returning something else. For the component inside, this is not a problem, but if we want to expose the method of this component to the parent component through a template reference, then there is a problem
We can call expose() Solve this problem:
{ setup(props, { expose }) { const count = ref(0) const increment = () => ++ expose({ increment }) return () => h('div', ) } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Rendering functions</title> </head> <body> <div > <button @click="add">add1</button> <my-child ref="child"></my-child> </div> </body> <script src="../lib/"></script> <script> const { h, ref } = Vue const Child = { // Writing method 1: // template: `<div>child</div>` // Writing method 2: // render () { // return [ // h('div', 'child!') // ] // } // Writing method 3 setup (props, { expose }) { const count = ref(10) const increment = () => { += 1 } expose({ increment }) // Return a function Function returns the result of the rendering function return () => h('div', 'child!!' + ) } } ({ components: { MyChild: Child }, setup () { const child = ref() const add = () => { () } return { child, add } } }).mount('#app') </script> </html>
This is the end of this article about the detailed explanation of the setup() function in vue3. For more related content of the vue3 setup() function, please search for my previous article or continue browsing the related articles below. I hope everyone will support me in the future!