-
👋 Hi! Is it possible to set component options inside the setup before the router resolves? Here's the code: export default viteSSR(
App,
{
pageProps: {
passToPage: false,
},
routes,
},
(context: SSRContext) => {
const { app, initialState, router } = context
const head = createHead()
app.use(head)
router.beforeResolve((to, from, next) => {
// Works only after the route is resolved and I re-enter the same page :(
const myMethod = to.matched[0]?.components?.default?.myMethod
if (myMethod) {
myMethod()
}
next()
})
app.component(ClientOnly.name, ClientOnly)
app.provide('initialState', initialState)
return {
head,
}
},
) <script lang="ts" setup>
const instance = getCurrentInstance()
if (instance && instance.proxy) {
instance.proxy.$options.myMethod = () => console.log('Hello, world')
}
</script> The problem is that until the setup function is called, I cannot add the attribute to the Right now, I'm working for a solution like in Nuxt (asyncData), but with composable inside setup and I need a way to prevent the routing resolving before the asyncData promise will be finished, so I thought I can add a method in the component instance to prevent the router. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
I don't think this is possible with a pure Composition API approach. You could add a second In any case, I think the Composition API gives you different ways to do this that might be simpler, such as |
Beta Was this translation helpful? Give feedback.
-
@frandiox, Thank you for your help. I thought for a while and came up with this solution, maybe someone will find it useful: Initialization// modules/asyncData.ts
import type { RouteComponent, RouteLocationNormalized } from 'vue-router'
import type { SSRContext } from '..'
type RouteComponentWithAsync = RouteComponent & {
asyncData?: <T>(context: SSRContext) => Promise<T> | T
}
type RouteLocationWithHref = RouteLocationNormalized & {
href?: string
}
export function installAsyncData(context: SSRContext) {
context.router.beforeResolve(async (to: RouteLocationWithHref, from: RouteLocationWithHref, next) => {
const initialState = context.initialState || {}
if (from.href) {
initialState.pageData = null
}
const [firstMatch] = to.matched || []
if (!firstMatch) {
return next()
}
if (!initialState.pageData) {
const asyncData = (firstMatch.components as Record<string, RouteComponentWithAsync>)?.default?.asyncData
if (typeof asyncData === 'function') {
let response = await asyncData(context)
if (Array.isArray(response) || typeof response !== 'object') {
console.warn('AsyncData should return an object!')
response = {}
}
initialState.pageData = response
}
}
next()
})
} // main.ts
import type { SharedContext } from 'vite-ssr/utils/types'
import { installAsyncData } from './modules'
export type SSRContext = SharedContext & {
app: VueApp
router: Router
}
export default viteSSR(
// ...
async (context: SSRContext) => {
const { app } = context
const head = createHead()
app.use(head)
app.component(ClientOnly.name, ClientOnly)
installAsyncData(context)
return {
head,
}
},
// ...
) Access to the
|
Beta Was this translation helpful? Give feedback.
@frandiox, Thank you for your help. I thought for a while and came up with this solution, maybe someone will find it useful:
Initialization