vue router back browser button - vue.js

At the moment, when I get to the detail page, the ID I need is taken from the url parameters, but if I go to another detail page and try to return to the previous one, the url is not updated and the data is not updated
What needs to be done to change the url ?
or use some native popstate or some like this
performance.getEntriesByType('navigation')
.map(nav => nav.type)
.includes('back_forward')

Are you using history option with createRouter?
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
...
})
Edit:
I put together a small demo that you can try. On a very basic level, it is simulating router history.
https://codesandbox.io/s/router-history-with-parameters-yv002y

Related

What are the implications of migrating from createWebHashHistory() to createWebHistory()?

I have an application that I released that uses createWebHashHistory() to manage URLs. For example, a user visits the following URL to visit something called the earthquakes channel:
https://app.radar.chat/#/channel/earthquakes
I would like to switch over to using createWebHistory() to manage URLs instead (SEO, social media previews, iOS universal links configuration, etc). With that in mind, I would like it if my new URL structure looks like this:
https://app.radar.chat/channel/earthquakes
I know that to support this change I need to make a server change. The easiest way is to have the server redirect incoming requests to an index.html file (this is documented extensively on the Vue website).
However, there are URLs in the wild that link to these old pages, URLs that have been printed and that can never be updated.
Is there a convenient mechanism to continue to support the old hash-based URLs while having the non-hashed URLs be the new default?
In your router config, you could add a global beforeEach hook on the index path that resolves to the hash path in the URL if it exists:
// router.js
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [⋯]
})
router.beforeEach((to, from, next) => {
if (to.path === '/' && to.hash.startsWith('#/')) {
next(to.hash.substr(1))
} else {
next()
}
})
export default router
demo

How to remove the hashtag in the url with vue router?

I read online that the hashtag in the url is caused by not using history in the vue router.
Currently, I am working on a big project and it would be a timewaste to start over and select history mode in the terminal.
That is why I would like to ask if it is possible to use switch to history mode while the vue project is already generated?
This is my url: http://localhost:8081/#/
The default mode for Vue router is hash-mode. You don't need the install the whole app again, just update the mode to history mode in your app where you have defined the vue router as follow:
For router v3:
const router = new VueRouter({
mode: 'history'
})
For router v4:
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
})
For reference:
https://next.router.vuejs.org/guide/#javascript

Vue 3 access to app level provided instances from vue-router

I want to write some complicated guard logics in vue-router in Vue 3 to protect entering some routes according to store and my other provided modules. For example, I want to check if user profile info is present or not:
router.afterEach((to, from) => {
console.log('store: ', useStore());
const puex = usePuex();
puex.isReady().then(() => {
const me = puex.me.compute();
watch(me, (...params) => console.log('router: ', ...params));
});
});
In the above code, useStore and usePuex both try to inject store and puex instances from Vue app which are provided while being used in main.js bootstrap. But both use functions return undefined and I guess that the inject in this scope searches a different place where app-level provided instances do not exist.
So how can I inject them in the router file, or in other words how can I get store and puex instance using useStore and usePuex here?
I have found a way according this question but I still don't know if it is the best available solution. I can export the app instance from main.js file and then use app.$store and app.$puex instead. Although it works, I still think about a better solution to inject the store and puex instance using use functions (inject).
You still can add the navigation guards after that your app has mounted in main.js/ts, the code would look like:
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const vm = createApp(App)
.use(puex)
.use(router)
.mount('#app');
router.afterEach((to, from) => {
const me = vm.puex.me.compute();
watch(me, (...params) => console.log('router: ', ...params));
});
You still can export that vm, to import it in the router file and use it the same way, but I really find somehow confusing, as main.js/ts is already importing the router file.

Vue.js with VueRouter - how to correctly route on user's refresh

I use Vue and VueRouter (and also Vuex but it is not the case here) in my project. Imagine i have 5 files:
main.js - stores all components definitions, imports them from
external files and so on.
App.vue - it is main component that stores
all other
routes.js - stores all the routing definitions
login.vue -
stores login component (login page)
content.vue - stores page
component
(quite simplified version but you surely get the idea).
Now if i open my path '/' it should reroute me to '/login' page if i am not logged in and to '/content' when i am logged in. Nothing special here.
Now my page works as intended (almost). If I enter in my browser '/content' it tries to render '/content' component with default data (ie userId = -1), then immediately it reroutes me to '/login' page. The '/content' shows just for a second. And it is my problem. I would like to reroute to '/login' without earlier rendering '/content' with default data.
It is obvious that it tries to render '/content' - maybe from cache or something, but since rerouting is my first command in created() it should not
mount /content component in app component, but /login.
Any idea how to prevent it?
I am aware that i do not attach any code, but i hope it wont be necessery for you to understand the problem and advice any solution because it would need cutting and simpliding a lot of code.
In your case, I think you should use vue router's beforeEach hook.
You can use meta field in router to indicates whether the path need authentication, and do processing in beforeEach function.
I will give the sample code.
import Router from 'vue-router';
const router = new Router({
routes: [{
path: '/content',
meta: {
auth: true,
}
}, {
path: '/login',
}]
});
router.beforeEach(async (to, from, next) => {
if (to.matched.some(m => m.meta.auth)) {
// user your authentication function
const isAuth = await getAuthentication;
if (!isAuth) {
next('/login');
}
next();
}
})
if your authentication function is not async function, you should remove async/await keywords
Except if the API in the meantime declares that you are no longer authenticated, the router will not be able to refresh itself by the beforeEach method.
Even with a loop method that retrieves data from the API, which will store them in the store as reactive data.
In Vue everything can be reactive, except Vue router

How to mix laravel and Vue2 router together

So In my laravel app we have a url say
http://mywebsite.in/wfengine/search/
Now I want to use the laravel router to work on the above link , but nothing seems to be happening.
Router.js
import VueRouter from 'vue-router';
let routes = [
{
path:'/filters',
componenet: require('./views/filter')
}
];
export default new VueRouter({
routes
});
App.js
`import router from './routes';
// import './core/searchableCards';
var app = new Vue({
el:'#ep_result_1',
router
})`
HTML
<router-link to="/filters">Search Page</router-link>
Now on the page which is loaded by laravel , I get following url in the browser
http://mywebsite.in/wfengine/search/#filters
But the template is not loading , can anyone help me out with this
According to me the Vue Router is just doing some Dom hide and show so it should not be effected by the base url right ?
Vue router mounts the components (defined in the routes array).
So if you defined a laravel routes to wfengine/search/ for the (e.g.) search.blade.php there should be the <router-view></router-view> dom element, as the doc says.
After that you should define the vue-router:
const router = new VueRouter({
mode: 'history',
routes
})
The routes variable is the routes array, the mode is for use the vue routing without # (http://mywebsite.in/wfengine/search/#filters -> http://mywebsite.in/wfengine/search/filters).
After that you should register the url (wfengine/search/filters) in the web route in laravel, what is give back the search.blade.php or that "base page" what contains the <router-view> dom.
So 1. there should be a base php view, what contains the <router-view>.
2. Then register the urls in the server side what gives back the same base view. 3. Then the vue-router will decide which component should be loaded by the end of the url.
At the end of your routes/web.php file just put the below code. This tricks works for me.
// At the end of the file
Route::get('/{vue_capture?}', function () {
return view('welcome');
})->where('vue_capture', '[\/\w\.-]*');
Of course you have to put a <router-view></router-view> into your layout or blade file.