Closed AxelBriche closed 2 years ago
First you can use nuxt-link
for external links now. Check the doc: https://v3.nuxtjs.org/docs/usage/nuxt-link.
If you still need to use it in is
prop, you can use defineNuxtLink({})
instead of nuxt-link
:
const component = computed(() => {
if (props.to || props.href) return defineNuxtLink({})
return 'button'
})
Or, to reuse the existing NuxtLink component:
const component = computed(() => {
if (props.to || props.href) return resolveComponent('NuxtLink')
return 'button'
})
Example: https://stackblitz.com/edit/github-vwzpk9?file=app.vue.
The reason this is required is that if you don't use NuxtLink it won't be included in your bundle. So we need more than just a string to tell us.
If you want it globally registered then you can create your own NuxtLink component with defineNuxtLink
in your components
directory and set components.global
to true in your nuxt.config
. See https://github.com/nuxt/framework/pull/3305 for some context.
Does resolveComponent
work only in an SFC context? 🤔
I tried it in a .vue file, it returns the actual component
I tried in a .ts file, it returns NuxtLink
string
There's kinda strange behavior when I try to resolveComponent
inside of ui-library. It cant resolve NuxtLink component
I have a nuxt page where I use a link component:
<template>
<base-link as="nuxt-link">Link</base-link>
</template>
<script setup>
import BaseLink from '@private-library/ui';
</script>
The components looks like
<template>
<component is="linkComponent" ...>
...
</template>
<script ...>
...
const linkComponent = resolveComponent('NuxtLink');
// console.log(linkConponent); -> null
</script>
@Dodje It's because NuxtLink isn't globally registered - it's auto-imported. Within a Nuxt project we detect resolveComponent('NuxtLink')
and rewrite this into an import statement.
You can probably resolve this in your case by adding your ui library to build.transpile
, and using import { NuxtLink } from '#imports'
...
@danielroe thanks for a quick response
Due your suggestion I was able to create ConcreteComponent with import { defineNuxtLink } from '#imports'
(or just import NuxtLink
from #components
, and it seems to work fine on server side, but i'm getting error "Failed to resolve component: NuxtLink" on the client side after hydration
I'll happily look at a reproduction.
Sometimes life is like a joke, I've created a reproduction repo and... it works just fine :) Tried again in the project, and it works too.. So, thanks again 👍
Excellent. 👌
@danielroe import { NuxtLink } from '#imports'
does not work for me.
Internal server error: [unimport] failed to find "NuxtLink" imported from "#imports"
For those wondering, the correct import is import { NuxtLink } from '#components';
Then you can use: <component :is="to ? NuxtLink : 'div'" :to="to">
,
Nuxt need better documentation about the Virtual Files, they are helpful, but confusing.
I'm having issues with this when generating a NuxtLink using a dynamic component in an external library.
I'm trying to support both Vue and Nuxt projects, so I have a component that detects the environment and renders the correct component (see below).
// How I'm detecting the environment/resolving the component
function computeTag(to: string | undefined) {
const instance = getCurrentInstance();
if (!instance || !instance.proxy) {
throw new Error('No instance of Vue detected');
}
const hasNuxt = instance.proxy && '$nuxt' in instance.proxy;
const hasRouter = instance.proxy && '$router' in instance.proxy;
if (!hasRouter || (hasRouter && !to)) {
return 'a';
}
return hasNuxt ? resolveComponent('NuxtLink') : resolveComponent('router-link');
}
// The component template
<component
:is="computedTag"
v-bind="computedProps"
>
<i v-if="icon" :class="icon"></i>
<span class="font-light">
<slot></slot>
</span>
<i v-if="isExternal" class="ml-auto pi pi-external-link" style="font-size: 0.75rem;"></i>
<Badge v-else-if="badge" class="ml-auto" :class="badgeClass" :value="badge"> </Badge>
</component>
The works for Vue projects but on Nuxt projects it is unable to resolve the NuxtLink component. Is there something I'm missing or is this just not possible with Nuxt?
I should also add that this library is written using just Vue, not Nuxt, due to some other restrictions.
------EDIT --------
After spinning my wheels on this for a few hours I fixed the issue within 2 minutes of posting this, typical.
It seems like the Vue instance isn't actually aware of the NuxtLink when it renders my component, I'm guessing has something to do with Nuxt's auto-importing. So, as part of my library import I added this to my plugin definition:
// ./plugins/my-ui-library.ts
import { defineNuxtPlugin } from "#app";
import { NuxtLink } from "#components";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component("NuxtLink", NuxtLink);
});
Can someone confirm if this is the right way to resolve this issue and maybe give a bit of clarification as to why it works?
Yes, that's a very reasonable solution. The only reason we don't register NuxtLink globally as if you don't use it we can tree-shake it out of your build.
For those wondering, the correct import is
import { NuxtLink } from '#components';
Then you can use:<component :is="to ? NuxtLink : 'div'" :to="to">
, Nuxt need better documentation about the Virtual Files, they are helpful, but confusing.
This doesnt seem to work, getting this all the time:
Property "NuxtLink" was accessed during render but is not defined on instance
@deflexor it will work if you use a script setup block, where the import is automatically exposed. Otherwise you need to pass it explicitly to the template.
Environment
Darwin
v14.18.2
3.0.0-27468803.23e7afb
yarn@1.22.17
vite
css
,build
-
Build Modules:
-
Reproduction
<component is="NuxtLink" to="/">Example</component>
Generate this html:
<nuxtlink to="/">Example</nuxtlink>
Expected html:
<a aria-current="page" href="/" class="router-link-active router-link-exact-active">Example</a>
Describe the bug
Usage of
<component is="NuxtLink" to="/">
doesn't generate a link, I can't use<component :is="to ? 'NuxtLink' : href ? 'a' : 'button'"
Additional context
No response
Logs
No response