Why router link have diferent behavior in mobil view? - vue.js

When I use router links in desktop view works fine but in mobile view the links lack the "/" to work, any idea to make it work for mobile (I mean when max-width change) (bootstraps makes all the jobs). I think a parameter or something to keep it working if bootstraps changes to a copy the menu adapted to mobile screen. In that swap of styles bootstrap stripes the "/" to the links with router vue link to. Any advice, suggerence or sample link will appretiated.

You should read this.
Vue Router Child, Trailing slash
Also to prevent this you can use strict in vue-router as follows
const route1 = { template: '<div>Route 1 (strict)</div>' }
const route2 = { template: '<div>Route 2 (no strict)</div>' }
Check the fiddle link
http://jsfiddle.net/L7hscd8h/9377/

Related

Vue Router - Nested Routes Not Working as Expected

I'm trying to create a simple nested routing:
App (root component, main navigation)
Topic1 (sub-navigation)
Topic1/Sub
Topic2
My demo on Codesandbox has the following issues:
1. When navigating from /topic1 to /topic1/sub, I expected the content from topic1 to show up and the content from topic1/sub to be shown below, like this:
However, Topic 1 does not show anymore.
2. How can I avoid showing "App" twice?
I know I've added path: "/topic1", component: App, but only because without it the routing did not work at all. As per the comments in router/index.js:
component: App, // Option 1 - Navigation to topic1,2 and /sub works (why?) 'App' is displayed twice
component: Topic1, // Option 2 - Navigation to /sub does not work but at least 'App' is only displayed once
I seem to be missing something essential - thank you already for any answers.
App component is showing twice because it is mounted twice. First it is mounted in main.js when you create the app. Then it is mounted in router-view as the route component. To avoid this, you shouldn't use the App component in router, instead make another Layout component where you define the page layout to be used by the vue-router. Also, this will allow the scenario where, while having a single entry point for your app (App), you can define different layouts for different routes, if needed.
Regarding the first question, the content of Topic1 component is not shown when navigating to Sub route, because it is wrapped in router-view. router-view displays only the content of the current route component. Avoid placing any content in router-view as it will be replaced on route navigation. This will work:
<h1>Topic1</h1>
<h2>Topic1 Content</h2>
<p>
<router-link to="/topic1/Sub">/topic1/sub</router-link>
</p>
<router-view> </router-view>
Here is the working codesandbox.
Also I refactored a bit your router index.js.

Is it possible to add .html at the end of the URL as you like while using NuxtJS or NextJS?

I am currently planning to develop a web application using NuxtJS/NextJS framework with SSR Universal architecture, I am facing difficulties related to SEO, because previously my project was written in .NET , so all URLs have .html at the end..
Ex:
domain.com/hotels (this is Cate)
domain.com/hotels-5-star.html (this is a Sub cate of Hotels Cate)
The example above is specific to my problem, which means that according to Google, the shorter the URL, the better, so my pages have all been shortened to a single "/", however because of the structure page has 2 hierarchies, Cate and Sub cate, so for Google to distinguish this, the URL (sub cate) must insert .html at the end.
Can I use NuxtJS/NextJS build pages with the same URL as above?, I have researched but found a specific solution, maybe my experience is not much so I need the help of experts on NuxtJS/NextJS
yeah, in nuxtjs, you can use #nuxtjs/router to custom your router path like this
nuxt.config.js
buildModules: [
'#nuxtjs/router'
]
router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const page = path => () => import(`./pages/${path}.vue`).then(m => m.default || m);
const routes = [
{
path: '/hotels-:star-star.html',
name: 'hotels',
props: true,
component: page('hotels')
}
];
export function createRouter(){
return new VueRouter({
routes
});
}
pages/hotels.vue
<template>
<main>
{{ star }}
</main>
</template>
<script>
export default{
props: {
star: {
type: Number
}
}
}
</script>
I'm not an expert in SEO, but I would just use 5-star as a query in domain.com/hotels
This would mean you could use the single hierarchy like so:
domain.com/hotels?rating=5-stars
As far as using html files as URL routing for the site, the nuxt generate property builds the project into html files which is under your control. The structure comes from what you set in the pages directory
Nowadays, all modern apps are having some pretty URLs looking like domain.com/hotels/
With a trailing slash at the end. Don't mix and match them. Either put them everywhere or nowhere.
SEO-wise, trailing slashes do not matter, you can let them.
Modern JS frameworks are doing a great job at this, and they know that if you reach domain.com/hotels/, you're actually wanting to serve the .html (aka the .vue) file in it, no need to add it.
In Nuxt.js, the directory structures would look like this:
-- pages
---- hotels.vue
or
-- pages
---- hotels
------ index.vue
As for this
the shorter the URL, the better
Don't stress it too much, you don't need to make super shorts paths neither.
Just keep it semantic and logic. Having domain.com/h5s will be super bad.
Also, having domain.com/hotels/5-stars or domain.com/hotels/?rating=5 is totally fine.
Basically, make them somehow readable for the end user.
PS: be aware that Next.js >> React and Nuxt.js >> VueJS.

Vue router: this.$route.fullPath does not reflect what it's in address bar?

I'm trying to get a handle on how Vue Router works and I'm not sure why if I console.log(this.$route.fullPath) in updated() {} the result does not match what's in my browser address bar.
I do understand that window.location.href might be what I want, but I want to know why $route.fullPath isn't the current window location (beginning with the URI components that is at least)?
Because the Vue router only concerns itself with the fragment part of the URL, i.e. the part after the # sign.

Vue + Vuetify + vue-router: changing toolbar content based on page

Vuetify has a pretty flexible layout scheme encompassing a menu, toolbar, content, and footer, that allows some nice-looking material design schemes, e.g. Google Contacts:
Consider a standard setup with the layout being controlled by the router, with a fixed menu across the site, but a dynamic toolbar that changes with the page shown. What's the best practice for changing the content of the toolbar depending on what page is shown? In the Google Contacts example, we only want the search bar to show up on the Contacts page.
Based on my rudimentary knowledge of Vue, it seems like defining a router layout with a scoped slot. There are likely a lot of other hacky ways to achieve this. But I'm looking for a clean, modular way to define toolbar content across pages.
Ideas:
As of a while ago vue-router didn't support named slots. But this seems to have changed recently, although there is no documentation.
Named views seem to be a nice way to support tie the toolbar content to the main page with vue-router. But there doesn't seem to be a good way for the toolbar to 'talk' to the main page as there would be with a slot.
You can define multiple router views in your application. Imagine your layout looks extremely simplified like this:
<v-app id="app">
<router-view name="navigation"></router-view>
<router-view></router-view>
</v-app>
Then you can define a route with components for both router views:
{
path: '/hello',
components: {
default: MyHelloComponent,
navigation: MyNavigationForHelloComponent
}
}
Documentation
Working Example from Documentation

Can Vue-Router handle clicks from normal anchors rather than router-link?

I have a scenario where there are two major components on a page; a frame-like component that contains common functionality for many applications (including a bookmark/tab bar) and my actual application code.
Since the frame doesn't actually own the page that it's included on, it seems like it would be incorrect for it to define any routes, however the current page may define their own routes that may match one of those links. In that case, I'd like vue-router to handle those anchor clicks and navigate appropriately rather than doing a full page reload.
Here's a simplified template of what this looks like:
Frame (an external dependency for my app):
<Frame>
<TabStrip>
</TabStrip>
<slot></slot>
<Frame>
App1:
<Frame>
<App>You're looking at: {{ pageId }}!</App>
</Frame>
So when any of the app1 domain links are clicked from that tab strip, I want my route definitions in app1 to pick that up rather than it causing a page load. Since that component is owned by the frame, I don't have access to write <router-link> since links to many different apps may co-exist there.
Any thoughts?
Whoo, this is an old one! However, since this question was high in my search results when I was researching this problem, I figured I should answer it.
My use-case was similar to the one in the comments: I needed to capture normal <a> links within rendered v-html and parse them through the router (the app is rendering Markdown with a light modification that generates internal links in some cases).
Things to note about my solution:
I'm using Vue3, not Vue2; the biggest difference is that this is the new Vue3 composition-style single page component syntax, but it should be easy to backport to Vue2, if necessary, because the actual things it's doing are standard Vue.
I stripped out the markdown logic, because it doesn't have anything to do with this question.
Note the code comment! You will very likely need to design your own conditional logic for how to identify links that need to be routed vs. other links (e.g. if the application in the original question has same-origin links that aren't handled by the Vue app, then copy/pasting my solution as-is won't work).
<script setup>
import { useRouter } from "vue-router"
const router = useRouter()
const props = defineProps({
source: {
type: String,
required: true,
},
})
function handleRouteLink(event) {
const target = event.target
// IMPORTANT! This is where you need to make a decision that's appropriate
// for your application. In my case, all links using the same origin are
// guaranteed to be internal, so I simply use duck-typing for the
// properties I need and compare the origins. Logic is inverted because I
// prefer to exit early rather than nest all logic in a conditional (pure
// style choice; works fine either way, and a non-inverted conditional is
// arguably easier to read).
if (!target.pathname || !target.origin || target.origin != window.location.origin) {
return
}
// We've determined this is a link that should be routed, so cancel
// the event and push it onto the router!
event.preventDefault()
event.stopPropagation()
router.push(target.pathname)
}
</script>
<template>
<div v-html="source" #click="handleRouteLink"></div>
</template>