Recently, a little partner has talked to me about setup function, because they are used to the vue2.x writing, which makes setup strange to use. In some api cases, the code becomes more confusing, and I feel that using setup in a more engineering-minded team really makes better use of modular development. But poorly used words do reduce the readability of the code. This article is about the practical use of setup from a usage perspective.
1. Setup does not conflict with previous api (data, methods, computed, etc.) and can be accessed from one another. It is worth noting that this is not available in setup and that the component instance was not created when setup was executed, so the variables and functions defined by data, methods, and computed cannot be used. An example of mixing is as follows:
import { getCurrentInstance} from 'vue' setup() { const count = 10; // Non-responsive. const { proxy } = getCurrentInstance(); // Here proxy equals this console.log(proxy.msg) // Cannot access properties inside data on setup call return { count, consoleMsg: () => { console.log(proxy.msg) // 123, accessible when you click the button } } }, data() { return { msg: '123' } }, created() { console.log(this.count) // 10, then you can access the properties thrown by setup. }
2. setup can also return a rendering function, but returning a rendering function will prevent us from returning anything else. Export can be used to handle this problem when we want to leak the function for use by its parent component. Examples are as follows:
import { h, ref } from 'vue' export default { setup(props, { expose }) { const count = ref(0) // Create a responsive variable const increment = () => ++count.value expose({ increment }) return () => h('div', count.value) // Note here that we need to explicitly use ref's value } }
Seeing here, we can use setup to do the project completely. Next, we will close the mountain and open the road to meet water bridges. If we don't, we will do all kinds of checks. Touches will always succeed. However, a post can't be written here and it's over. There is still a lot of related knowledge behind it.
ResponsiveWhy talk about responsiveness, because the variable returned from setup can be used directly in the template syntax, but it is not responsiveness, as in the first example above, if we used {} in the template to show the value of count, then we changed the value of count, but the display did not change.
// Non-responsive examples, equivalent to error examples, try not to copy this code into your project. <template> <div> <span>{{ count }}</span> <button @click="count ++; consoleValue(count)">Increment count</button> </div> </template> <script> export default { setup() { let count = 10; // This is not responsive. return { count, consoleValue: (value) => { console.log(value); // The value has changed here } } } } </script>
The responsive one is more in the official website api, only a few are more used.
1. The ref mentioned above takes a parameter and wraps it back in an object with a value property, which can then be used to access or change the value of the responsive variable. In the simplest case, the above example changes to a responsive one, as follows:
<template> <div> <span>{{ count }}</span> <button @click="count ++">Increment count</button> <button @click="doubleCount">double count</button> </div> </template> <script> import { ref } from 'vue' export default { setup() { let count = ref(10); return { count, doubleCount: () => { // It's worth noting that you need to use.value to access within the setup count.value *= 2; } } } } </script>
2. reactive returns a responsive copy of the object. This is understandable and not very different from the previous 2.x era.
<template> <div> <span>{{ countObj.count }}</span> <button @click="countObj.count ++">Increment count</button> <button @click="doubleCount">double count</button> </div> </template> <script> import { reactive } from 'vue' export default { setup() { const countObj = reactive({ count: 10 }); return { countObj, doubleCount: () => { countObj.count *= 2; } } } } </script>
3. Both toRef and toRefs functions are designed to obtain a responsive subitem and associate it with previous responsive data.
<template> <div> <div>{{ countObj.count }} {}</div> <div>{{ count }} {{ changeTimes }}</div> <button @click="count ++; changeTimes ++">increment count</button> <button @click="doubleCount">double count</button> </div> </template> <script> import { reactive, toRefs, toRef } from 'vue' export default { setup() { const countObj = reactive({ count: 10, changeTimes: 0 }); const { count } = toRefs(countObj); const changeTimes = toRef(countObj, 'changeTimes'); return { countObj, count, changeTimes, doubleCount: () => { countObj.count *= 2; changeTimes.value ++; } } } } </script>
Note: toRefs only generates refs for the properties contained in the source object. If you want to create a ref for a particular property, you should use toRef, a simple and rude understanding of toRef adds an associated responsive property to the source object, such as: (I wanted to write it in the example above, but it didn't feel clear, I listed a separate pseudocode)
const countObj = reactive({ count: 10 }); const testV = toRef(countObj, 'test'); testV.value = 10; console.log(countObj.test); // 10setup parameter
Use setup When a function is executed, it takes two arguments:
Props
Setup The first parameter in the function is props. As expected in a standard component, setup In functions props Is responsive and will be updated when a new prop is passed in.
export default { props: { title: String }, setup(props) { console.log(props.title) } }
But because props It's responsive, you can't deconstruct with ES6, it eliminates prop responsiveness, toRefs mentioned above can solve this problem very well.
import { toRefs } from 'vue' setup(props) { const { title } = toRefs(props) console.log(title.value) }
If title Is an optional prop, then the props Possibly not in title . In this case, toRefs Will not title Create a ref. You need to use toRef Replace it:
import { toRef } from 'vue' setup(props) { const title = toRef(props, 'title') console.log(title.value) }
Context
Pass to setup The second argument to the function is context. context Is a generic JavaScript object that exposes other possibilities setup Useful values in:
export default { setup(props, context) { // Attribute (non-responsive object, equivalent to $attrs) console.log(context.attrs) // Slot (non-responsive object, equivalent to $slots) console.log(context.slots) // Trigger event (method, equivalent to $emit) console.log(context.emit) // Exposing public properties (functions) console.log(context.expose) } }setup life cycle hook
The following life cycle hooks are accessible in setup:
- onBeforeMount
- onMounted
- onBeforeUpdate
- onUpdated
- onBeforeUnmount
- onUnmounted
- onErrorCaptured
- onRenderTracked
- onRenderTriggered
- onActivated
- onDeactivated
These functions accept a callback function that will be executed when the hook is called by the component, such as:
export default { setup() { // mounted onMounted(() => { console.log('Component is mounted!') }) } }
The original is not easy to reproduce, please indicate the source, welcome the message proposal.