I have a navbar with a menu that users can click on. Some links will need to open up a new tab. This is what I have and I couldn't get it to work.
<template>
<nav>
<v-app-bar text app color="blue">
<v-app-bar-nav-icon class="white--text" @click="drawer = !drawer"></v-app-bar-nav-icon>
<v-app-bar-title class="text-uppercase white--text">
<span class="font-weight-light">Logo</span>
<span>Global</span>
</v-app-bar-title>
</v-app-bar>
<v-navigation-drawer v-model="drawer" app class="grey lighten-1">
<v-list>
<img class="ml-5 mb-3" src="../assets/Logo-Blue.png" width="70" />
<v-list-item v-for="link in links" :key="link.text" router :to="link.route" @click="go(link)">
<v-list-item-action>
<v-icon>{{ link.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title> {{ link.text }} </v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
</nav>
</template>
<script>
export default {
data() {
return {
drawer: true,
links: [
{ icon: 'home', text: 'Dashboard', route: '/dashboard', newTab: false },
{ icon: 'leaderboard', text: 'Stats', route: 'www.google ', newTab: true },
]
}
},
methods: {
go(link) {
console.log('go run ...')
console.log(link)
console.log(process.env.APP_URL)
if (!link.newTab) {
this.$router.push({ path: link.route })
} else {
window.open(link.route)
}
}
}
}
</script>
src/router/index.js
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
Did I do sth wrong ?
Open up a new tab seems to work, but it kept prepending my localhost URL.
I have a navbar with a menu that users can click on. Some links will need to open up a new tab. This is what I have and I couldn't get it to work.
<template>
<nav>
<v-app-bar text app color="blue">
<v-app-bar-nav-icon class="white--text" @click="drawer = !drawer"></v-app-bar-nav-icon>
<v-app-bar-title class="text-uppercase white--text">
<span class="font-weight-light">Logo</span>
<span>Global</span>
</v-app-bar-title>
</v-app-bar>
<v-navigation-drawer v-model="drawer" app class="grey lighten-1">
<v-list>
<img class="ml-5 mb-3" src="../assets/Logo-Blue.png" width="70" />
<v-list-item v-for="link in links" :key="link.text" router :to="link.route" @click="go(link)">
<v-list-item-action>
<v-icon>{{ link.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title> {{ link.text }} </v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
</nav>
</template>
<script>
export default {
data() {
return {
drawer: true,
links: [
{ icon: 'home', text: 'Dashboard', route: '/dashboard', newTab: false },
{ icon: 'leaderboard', text: 'Stats', route: 'www.google. ', newTab: true },
]
}
},
methods: {
go(link) {
console.log('go run ...')
console.log(link)
console.log(process.env.APP_URL)
if (!link.newTab) {
this.$router.push({ path: link.route })
} else {
window.open(link.route)
}
}
}
}
</script>
src/router/index.js
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
Did I do sth wrong ?
Open up a new tab seems to work, but it kept prepending my localhost URL.
Share Improve this question edited Dec 20, 2021 at 5:53 tony19 139k23 gold badges278 silver badges348 bronze badges asked Dec 19, 2021 at 16:59 code-8code-8 58.9k120 gold badges391 silver badges670 bronze badges 1- With window.open your vue-router should not be used, therefore your base URL shouldn't be added. Have you simply try to refresh your browser cache after changes? – jssDev Commented Dec 20, 2021 at 8:40
1 Answer
Reset to default 6Don't use a click
-handler with the v-list-item
, since that defeats the underlying anchor tag generated for the routing, and has accessibility implications. Stick with the v-list-item
's props that are built in for routing:
href
: To create an external link with<v-list-item>
, use thehref
prop. Internal links should useto
instead.target
: To open a new window upon clicking the link, use thetarget="_blank"
prop.
A v-list-item
that links to an external URL would use the href
prop like this:
<v-list-item href="https://google.">Google</v-list-item>
And one that opens a new tab would use the target="_blank"
prop:
<v-list-item target="_blank" href="https://google.">Google</v-list-item>
Internal links use the to
prop instead of href
:
<v-list-item to="/dashboard">Dashboard</v-list-item>
And they could be opened in a new tab with target="_blank"
as well:
<v-list-item target="_blank" to="/dashboard">Dashboard</v-list-item>
Solution
In your case, you have an array of items that need to bind the previously mentioned props conditionally. That's best done using v-bind
with an object (where the object's key-value pairs are bound as ponent props) that is puted based on each item's properties:
- Compute a new array of links (named
putedLinks
) that has a new prop to bind (namedlinkProps
):
export default {
puted: {
putedLinks() {
return this.links.map(link => {
const isExternalLink = url => /^((https?:)?\/\/)/.test(url)
const linkProps = {
[isExternalLink(link.route) ? 'href' : 'to']: link.route,
}
if (link.newTab) {
linkProps.target = '_blank'
}
return {
...link,
linkProps,
}
})
},
},
}
- Update the template to use
putedLinks
, and bind each link'slinkProps
to its correspondingv-list-item
:
<v-list-item v-for="link in putedLinks" :key="link.text" v-bind="link.linkProps">