-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
template ref can not get exposed value from a top level await component #4930
Comments
see #4891 (comment) |
@edison1105 I tried that, but I do not think it's a good workaround. As code below,
If I move 这种写法存在代码上的逻辑撕裂,如果可能的话请加以增强。 |
Currently, for template refs Vue relies on the presence of This is usually fine, but becomes a problem with an async component like the one in this issue, because here, So what we would need is a way to recognize that a component was created with But that would still leave us with a challenge: While the async component is still pending, So in summary:
So fix or not, the general recommendation should be to call |
@LinusBorg Thank you for your reply. Sometimes call Consider
The first option violates the logic of writing code, we always invoke a var after we declared it. Here we change the code order, only because we need let the The second option seems tobe a good choise than the first one, but still make the code reader confusion why we need split declare and init, where is the init code. So I think we should find a way to improve the |
@LinusBorg It would be nice if something was done to make Your idea of having the compiler set a
I don't think that's what happens. Another argument is that this is actually what people have to do today. If I'm correct whether you can call |
BTW, if Vue does not improve |
@jods4 |
@edison1105 To be honest it's not what I expected, based on @LinusBorg comment above. My main worry with your The approach I assumed from Linus' description was this:
instance.exposeProxy = new Proxy(instance, {
get(target, key: string) {
if (key in target.exposed) {
return unref(target.exposed[key])
} else if (key in publicPropertiesMap) {
return publicPropertiesMap[key](instance)
}
},
has(target, key: string) {
return key in target.exposed || key in publicPropertiesMap
},
})) It's worth noting that the proxy handler is identical for all instances, so it could be cached and reused for all components (saving a bit of memory). |
@jods4 <script lang="ts" setup>
const data = await fetch(...)
const getFoo = () => {
return data.foo
}
defineExpose({
getFoo,
})
</script> When expose relies on the result of an asynchronous request. Although this approach may be unreasonable, it is allowed. |
@edison1105 This example is exactly the improvement that this issue would like to perform. If expose does not rely on async results, then it can trivially be put at the top script setup. What is the fundamental problem that can't be solved in this example? |
Scenario 1:If export default {
async setup(_, { expose }) {
await fetch('...')
expose({
data: 'foo'
})
}
} We cannot handle this automatically. We must inform users through documentation to manually place Scenario 2:If <script lang="ts" setup>
const data = await fetch(...)
const getFoo = () => {
return data.foo
}
defineExpose({
getFoo,
})
</script> or export default {
async setup(_, { expose }) {
const data = await fetch(...)
const getFoo = () => {
return data.foo
}
expose({ getFoo })
}
} Before the async request completes (before the component mounts), if the parent component calls the child component's Conclusion:Considering the above two scenarios, regardless of whether |
This is the culprit. This playground I shared previously seems to confirm that it's a working solution. Adding properties to the exposed objects is also the work-around that we currently employ and I have not seen an issue with it so far. |
Version
3.2.21
Reproduction link
sfc.vuejs.org/
Steps to reproduce
click the button
What is expected?
without error
What is actually happening?
got an error
The text was updated successfully, but these errors were encountered: