This is code from main.js where I`ve configured my router
enter code here
const router = new Router({
routes,
mode: 'history',
saveScrollPosition: true
});
sync(store, router);
const app = new Vue({
router,
store,
render: h => h(App )
}).$mount('#app');
Then in vuex/actions.js I`ve action registerUser where I do request to API and if response is success I want to redirect user to main page
enter code here
export const registerUser = ({commit, state}, userData) => {
commit(types.REQUEST_USER_REGISTER);
api.register(userData).then(success => {
const response = success.data;
localStorage.setItem('id_token', response.token);
commit(types.USER_OBJECT, response.user)
//TODO: find better solution, then put router instance into window var
window.router.replace('/');
}, failure => {
})
}
This code above works well, because I`ve set router instance into window var in build.js, maybe somebody know better solution instead of it
Move router declaration to separate file and export it. Then import in main file and any other file which you wish to use it. The api is the same as for $router property on vue prototype.
Related
In my NextJS project, I created a custom server with koa + koa-session, so that I can have some session data per each request, like the code below,
import next from "next";
import Koa from "koa";
import Session from "koa-session";
import Router from "koa-router";
...
const next_app = next({...});
const handle = next_app.getRequestHandler();
next_app.prepare().then(async () => {
const server = new Koa();
const router = new Router();
server.use(Session(server)); // use koa-session middleware
...
router.get("(.*)", async (ctx) => {
console.log("server.js session: ", ctx.session);
...
// create or update session data
ctx.session.custom_data += 123;
// but how to pass ctx.session to handle(), then to page components?
await handle(ctx.req, ctx.res);
});
As said in the comment, how to pass ctx.session data to page components?
I have a Laravel / Vue app using SSR so have JavaScript running server side and client side.
I had a bug in my code where I was checking user.id when the user object was null.
If this had been running client side I would have seen the error in the console and easily fixed it.
However because this was running in v8js I got no output at all and was just a case of trial and error to locate and fix the bug. This reminded me of fixing JS errors in IE6 - not something I want to repeat!
I did try the getPendingException() method but this just gave me a warning about it being deprecated.
Note some errors are generated....
Obvious syntax errors are picked up straight away when I run webpack.
Some errors throw a V8JsScriptException:
if(foo.bar) {}
This generates the error:
V8Js::compileString():86354: ReferenceError: foo is not defined
If I wrap foo in a function and then call it:
function test() {
if(foo.bar) {}
}
test()
No exception is thrown, but the only output returned is:
ReferenceError: foo is not defined
However this code that is for my Vue router produces no output at all:
import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'
Vue.use(Router)
export function createRouter () {
const router = new Router({
mode: 'history',
routes: routes
})
router.beforeEach(async (to, from, next) => {
if(foo.bar) {}
next()
})
return router
}
When I run this same code in the browser the console shows:
ReferenceError: foo is not defined
So it seems JS is creating an error - but somehow V8Js is not passing it on.
Why does the undefined error in the Vue router not throw an exception when run in v8js?
Use an onError handler on your router: router.onError
And, since your beforeEnter guard is async, you'll need to call next with the error:
export function createRouter () {
const router = new Router({
mode: 'history',
routes: routes
})
router.beforeEach(async (to, from, next) => {
try {
if(foo.bar) {}
next()
} catch (e) {
next(e)
}
})
router.onError(err => {
print('<!-- router error: ' + err.message + ' -->')
})
return router
}
For your example, you could use a synchronous guard and do without the try/catch:
router.beforeEach((to, from, next) => {
if(foo.bar) {}
next()
})
I want to use koa-views with Koa and Koa-Router with Next.js. In previous projects, I had no issues with express but in this project, I have to use Koa. Using its router, I want to render a page: /some/page/:id. Following the same Nextjs way:
router.get('/some/page/:id', async (ctx, next) => {
const actualPage = '/some/page/id' // id.js (not actual name 😝)
await ctx.render(actualPage, {/* could pass object */})
});
That would work if I was using express. With Koa:
const Koa = require('koa');
const views = require('koa-views');
// const render = require('koa-views-render'); <-- I what's this?
[..] // Making things short here
const server = new Koa();
const router = new Router();
// My issue, I'm seeing tutorials using other engines: .ejs etc
// I'm not using any, I only have .js files
server.use(views(__dirname + "/pages", { extension: 'js' }));
Using the same router.get... function as above, I get:
Error: Engine not found for the ".js" file extension
When I go to /some/page/123, I'd expect it to render the file /pages/some/page/id.js. How?
It turns out I do not need any extra modules to achieve this 🙀
Create a function called, ie, routes then pass app and router as a param
const routes = (router, app) => {
router.get('/some/page/:id', async (ctx) => {
const { id } = ctx.params
const actualPage = '/some/page/id'
// Render the page
await app.render(ctx.req, ctx.res, actualPage, {foo: 'Bar'})
}
}
module.exports = routes
Inside your server.js file:
// const routes = require('./routes);
// const app = next({ dev }); // import other modules for this section
// app.prepare().then(() => {
// const router = new Router();
// [..]
// routes(router, app)
// })
The commented out section is a slim down version to make a point in where things should be.
I am using Vue, Vuex with Quasar (Quasar might or might not be irrelevant here)
This is my first Application and so I am not sure if I am doing things correctly or not
Below is the code snippet for my routes
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
/*
* If not building with SSR mode, you can
* directly export the Router instantiation
*/
const routes = [
{
path: '/',
component: () => import('layouts/MyLayout.vue'),
beforeEnter: ifAuthenticated ,
children: [
{ path: '', component: () => import('./../container/Index.vue') }
]
}
]
const ifNotAuthenticated = (to, from, next) => {
console.log("here")
if (!store.getters.isAuthenticated) return next()
else next('/')
}
const ifAuthenticated = (to, from, next) => {
if (store.getters.isAuthenticated) return next()
else next('/login')
}
export default function (store) {
const Router = new VueRouter({
mode: 'history',
routes,
// Leave these as is and change from quasar.conf.js instead!
// quasar.conf.js -> build -> vueRouterMode
// quasar.conf.js -> build -> publicPath
mode: process.env.VUE_ROUTER_MODE,
base: process.env.VUE_ROUTER_BASE
})
return Router
}
Here notice this line of code
const ifNotAuthenticated = (to, from, next) => {
console.log("here")
if (!store.getters.isAuthenticated) return next()
else next('/')
}
With this I was expecting to do client side authentication and based on my understanding/reading about client Authentication
I thought this would be called when I did something like this
beforeEnter: ifAuthenticated ,
But unfortunately that function isn't being called (since it isn't console logging anything).
Any idea of what I might be doing wrong?
You're not calling ifNotAuthenticated anywhere in your code, so you won't see the console log message.
It's probably easier and better to use global beforeEach guard for checking authentication. Here's a very simple example code how you can do it using meta data in your routes config.
I added comments in the code to explain things.
I recommend you to read Navigation Guards in Vue Router documentation.
Also a nice article explaining things more in detail.
const routes = [
{
path: "/dashboard",
name: "Dashboard",
component: () => import("path/to/Dashboard.vue"),
// Add a metadata like this to your private routes
// Tip: If you have a lot of private routes, you can add
// meta: { public: true } to public routes and make
// all other routes private by default.
// In this case you need to change the logic in beforeEach
// below.
meta: { requiresAuth: true },
},
];
export default function(store) {
const Router = new VueRouter({
mode: "history",
routes,
// Other stuff...
});
Router.beforeEach((to, from, next) => {
// See if any of the matched routes has meta "requiresAuth"
if (to.matched.some(route => route.meta.requiresAuth)) {
// Yes this route requires authentication. See if the user is authenticated.
if (store.getters.isAuthenticated) {
// User is authenticated, we allow access.
next();
} else {
// User is not authenticated. We can redirect her to
// our login page. Or wherever we want.
next("/login");
}
} else {
next();
}
});
return Router;
}
Let's say I have the following routes:
// routes.js
import PhotoRoutes from './photoRoutes';
const UserBaseRoute = Router();
UserBaseRoute.use('/api/:userId', PhotoRoutes);
// photoRoutes.js
const PhotoRoute = Router();
PhotoRoute.get('/', (req, res) => {
console.log(req.params);
res.end();
});
export default PhotoRoute;
When I hit /api/123/ I expect to use {"userId: 123}' But I don't. Why is the :userId defined in the baseRoute not passed up?
This is a issue related to nested router.
You need to set the mergeParams of child router as true to access params from parent router.
So try following code:
const PhotoRoute = Router({mergeParams: true});
BTW, this option came with Express version 4.5. For more details, refer to the API document