This article was first published on the WeChat public account: Big Move to the World, my WeChat: qq449245884, I will share with you the front-end industry trends, learning methods, etc. as soon as possible.
For more open source works, please see GitHub https://github.com/qq449245884/xiaozhi , including the complete test sites, materials and my series of articles for interviews with first-tier manufacturers.
With the release of Vue 3.2, a new composition tool is provided to us, called expose
.
Have you ever created a component that needs to provide some methods and properties to the template, but you want those methods to be private to the component and not be called by the parent class?
If you are developing an open source component or library, you may want to keep some internal methods private. Before Vue 3.2 this was not easy to achieve because all the methods or data etc declared in the options API were public so templates could access it.
The same goes for the composition API. Everything we return from the setup
method can be directly accessed by the parent class.
Combining APIs
Let's look at a practical example. Imagine we have a component that creates a counter that is updated every second.
MyCounter.vue
<template>
<p>Counter: {{ counter }}</p>
<button @click="reset">Reset</button>
<button @click="terminate">☠️</button>
</template>
<script>
import { ref } from 'vue'
export default {
setup () {
const counter = ref(0)
const interval = setInterval(() => {
counter.value++
}, 1000)
const reset = () => {
counter.value = 0
}
const terminate = () => {
clearInterval(interval)
}
return {
counter,
reset,
terminate
}
}
}
</script>
From a composition standpoint, I want the parent component to be able to directly call the reset
method when needed -- but I want to keep a reference to the terminate
function and counter
Only available for components.
If we instantiate this component into a parent class, say App.vue, and attach a ref reference to it, we can easily have the parent class call the reset
method, because when we start from setup
When returning it in setup
, it was already exposed along with terminate
.
App.vue
<template>
<MyCounter ref="counter" />
<button @click="reset">Reset from parent</button>
<button @click="terminate">Terminate from parent</button>
</template>
<script>
import MyCounter from '@/components/MyCounter.vue'
export default {
name: 'App',
components: {
MyCounter
},
methods: {
reset () {
this.$refs.counter.reset()
},
terminate () {
this.$refs.counter.terminate()
}
}
}
</script>
If you run this now, and click the reset or kill button, both work.
Let's be explicit about what we want to expose ( expose
) to the parent class so that only the reset
function is available.
MyCounter.vue
<script>
import { ref } from 'vue'
export default {
setup (props, context) {
const counter = ref(null)
const interval = setInterval(() => {
counter.value++
}, 1000)
const reset = () => {
counter.value = 0
}
const terminate = () => {
console.log(interval)
clearInterval(interval)
}
context.expose({ reset })
return {
counter,
reset,
terminate
}
}
}
</script>
Here, we have added props
and context
parameters to the ---a2d34b52c86f07d1fd950ea378caaec1 setup
function. We need to have context available because this is where the expose
function is located. We can also use refactoring like this: { expose }
.
Next, we use context.expose
to declare an element object that we want to expose to the parent class that instantiates this component; in this example, we only intend to make the reset
functionality available.
If we run the example again and click the "Terminate from parent" button, we'll get an error.
Uncaught TypeError: this.$refs.counter.terminate is not a function
terminate
The functionality is no longer available and our private API is now inaccessible.
Options API
Above we used ---3a7f880e6f49314ef26c918edade32c2 composition API
in exponse
, but this method can also be used in the options API. We can rewrite it as follows.
// MyCounter.vue
export default {
created () { ... },
data: () => ({ counter: null }),
methods: {
reset () { ... },
terminate () { ... }
},
expose: ['reset']
}
Note that we've added a new Options API property expose
that allows us to pass in an array where the string 'reset'
is the name of the function we expose.
Combining API rendering capabilities
The way to create a powerful and flexible component is to harness the power of render functions. This is not new to Vue 3, but with the establishment of the composition API, we now have the flexibility to return the composition API h
function directly from the setup
method.
This creates a problem because in our setup
function, the entire return
statement is just the h
method that contains the node the component is creating.
If at this point we choose to expose something to the parent class, we have the opposite problem to what we saw earlier. Nothing is exposed because nothing is returned except the DOM element.
Let's rewrite the MyCounter.vue
component to use this method.
<script>
// The template has been deleted
import { ref, h } from 'vue'
export default {
setup (props, context) {
const counter = ref(0)
const interval = setInterval(() => {
counter.value++
}, 1000)
const reset = () => {
counter.value = 0
}
const terminate = () => {
clearInterval(interval)
}
// context.expose({ reset })
return () => h('div', [
h('p', `Counter: ${counter.value}`),
h('button', { onClick: reset }, 'Reset'),
h('button', { onClick: terminate }, 'Terminate')
])
}
}
</script>
Note that we imported h
from Vue at the top, because we need it to create our DOM elements.
To illustrate the problem, the context.expose
method is temporarily annotated.
The return statement now replicates the DOM structure from our previous <template>
and if we run the example, we can click the reset and terminate buttons on the element correctly.
However, if we now click the "Reset from parent" button, we will encounter an error.
Uncaught TypeError: this.$refs.counter.reset is not a function
reset
method is no longer exposed because it was not returned by the setup
function. To fix this, we need to cancel the call to context.expose
to make it available again.
Summarize
The new expose
method is very intuitive and easy to implement in our component. It clears up some very important compositional issues that in the past even required rewriting a complete component, so even if it's not an API you use every day, it's worth keeping in our folder for ashes.
The bugs that may exist after the code is deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, I recommend a useful bug monitoring tool , Fundebug .
Author: Marina Mosti Translator: Front-end Xiaozhi Source: vuemastery
Original: https://www.vuemastery.com/blog/understanding-vue-3-expose/
comminicate
If you have dreams and dry goods, you can search for [Great Move to the World] on WeChat and pay attention to this Shawanzhi who is still washing dishes in the early hours of the morning.
This article GitHub https://github.com/qq449245884/xiaozhi has been included, there are complete test sites, materials and my series of articles for interviews with first-line manufacturers.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。