For some reason, this.$route is undefined for me. I have just started building my Vue application:
window.Vue = require('vue');
new Vue({
el : '#break-container',
data : {
break : null
},
methods : {
fetchBreak : function(){
console.log(this.$route); //undefined
},
},
mounted : function(){
this.fetchBreak();
},
});
I see a bunch of questions on SO about this, but every time the problem seems to be that they are using arrow notation.
In my case, when I do console.log(this) there is no $route key in the printed object at all. The keys ($attrs, $children, ... , $vnode, break).
What can I do to resolve this?
As I understand it, this.$route is only available on Vue instances if you register your router when you create your Vue app. Your code appears to be missing the router definition and subsequent initialisation on the Vue instance
new Vue({
el : '#break-container',
// Register your router
router: router,
data : {
break : null
},
methods : {
fetchBreak : function(){
console.log(this.$route); //undefined
},
},
mounted : function(){
this.fetchBreak();
},
});
See the sample code here for a full-fledged example. From the page above:
By injecting the router, we get access to it as this.$router as well as the current route as this.$route inside of any component
EDIT:
Pasting some example code from the link above for clarity. Note the steps 0-4 in the comments. Odds are, one of those steps are missing in your code :)
// 0. If using a module system (e.g. via vue-cli), import Vue and VueRouter
// and then call `Vue.use(VueRouter)`.
// 1. Define route components.
// These can be imported from other files
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. Define some routes
// Each route should map to a component. The "component" can
// either be an actual component constructor created via
// `Vue.extend()`, or just a component options object.
// We'll talk about nested routes later.
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. Create the router instance and pass the `routes` option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = new VueRouter({
routes // short for `routes: routes`
})
// 4. Create and mount the root instance.
// Make sure to inject the router with the router option to make the
// whole app router-aware.
const app = new Vue({
router
}).$mount('#app')
Related
I have
these simple route/URL when I am in a car details page
http://localhost:8080/car/1
I am using vue2; what is the best way to check if I am on a car page?
I normally
would have checked for the first segment of the URL, but I wasn't sure if that is the best future-proof approach.
Questions
Should I use JS to detect what page I am ?
Should I use Vue functionality to access the router object?
Why would one decide to pick one over another?
You could provide a name for your route inside the routes definition like :
{
path: '/car/{id}',
name: 'car',
component: CarView
},
then access it using this.$route.name or you could parse the this.$route.path to get the name using String object methods
Perhaps, try using: router.currentRoute.path, where router is:
import Router from "vue-router";
Vue.use(Router);
const routes = [
{ path: "/", component: Home },
{ path: "/test1", component: Test1 },
{ path: "/test2", component: Test2 }
];
const router = new Router({
routes
});
console.log('Current route: ', router.currentRoute.path);
Im having a simple import problem in my VueJS 3 app. I have looked at this answer: Vue 3 Composition API Provide/Inject not working in Single File Components but did not find an answer.
I am importing my external file in main.js: import * as myService from "./services/myService.js";
Then also in main.js: app.provide("myService", myService);
And then in my component I have:
<script>
export default {
name: "MyComponent",
props: {
...
},
methods: {
myFunc: function(){
var result = myService.serviceFunction();
}
},
data: function(){
return {
...
}
},
inject: ["myService"]
}
</script>
But where I have var result = myService.serviceFunction(); gives me the error that myService is undefined.
If I call var result = myService.serviceFunction(); in main.js there is no error and the function is called correctly, so the problem must be with the VueJS injection.
What have I done wrong?
You should add this to get access to the injected item :
methods: {
myFunc: function(){
var result = this.myService.serviceFunction();
}
},
In my router/index.js, I am trying to lazy-load the route. If I hard-code the string it is working but if I use a function (as shown) call to get that file path as a string value, it shows me an error in the console - Error: Cannot find module '../views/Login/Login.vue'. I'm using Vue 2.6.11 and Vue-router 3.5.1.
Where am I going wrong?
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// const filePath = (filename, foldername) => '../views/' + foldername + "/" + filename + '.vue'
const routes = [
{
path: '/',
name: 'Login',
// THIS WORKS
component: () => import('../views/Login/Login.vue')
// THIS DOES NOT, EVEN THOUGH IT IS GETTING THE EXACT SAME VALUE
// component: () => import(filePath('Login', 'Login'))
},
]
const router = new VueRouter({
routes
})
export default router
If you want to lazy-load a route, it has to be statically analyzable, like this:
component: () => import('../views/Login/Login.vue')
In your other attempt:
component: () => import(filePath('Login', 'Login'))
The import is not statically analyzable by the build tool (probably webpack). The build tool is in charge of identifying which code is being used and which code is not (that's called tree-shaking).
As it can't resolve the actual import (it would be possible only at runtime since filePath could return anything), it considers that the vue file is never referred to, and should be removed from the build.
If your actual build tool is webpack, you have to follow webpack's instructions described here: https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import which states that is possible to have dynamic imports when they have a statically analyzable pattern (e.g: template literals)
You should let webpack to know in which root folder it will load the component files, so you should move ../views/ to the import parameter instead of the returned value of your function :
const filePath = (filename, foldername) => foldername + "/" + filename + '.vue'
const routes = [
{
path: '/',
name: 'Login',
component: () => import('.../views/'+filePath('Login', 'Login'))
},
]
I have multiple entries like in webpack docs
module.exports = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
let's say every of these files (index.js) is the same and only thing that change is other routes import.
I would create one file to keep DRY principle but I would need to pass something to actually know which router I want to import.
For example pageOne/index.js is
import Vue from 'vue'
import axios from 'axios'
import App from '../App'
import { store } from '../store';
import VueProgressBar from 'vue-progressbar'
import Router from '../routers/router';
import interceptor from '../../config/httpInterceptor.js';
console.log('in main', window.location.href)
const routerInstance = new Router('main');
routerInstance.createRouter()
.then(router => {
interceptor();
if (!process.env.IS_WEB) Vue.use(require('vue-electron'));
Vue.http = Vue.prototype.$http = axios;
Vue.config.productionTip = false;
Vue.use(VueProgressBar, {
color: 'rgb(255, 85, 0)', failedColor: 'red', thickness: '5px'
});
new Vue({
components: { App },
router,
store,
template: '<App/>'
}).$mount('#app');
});
and in pageTwo/index.js only line that change is from
const routerInstance = new Router('main');
to
const routerInstance = new Router('second');
so it's bad to have three same js files where only one line is changing but I don't know how to refactor it so it's reusable. I would need to pass to file information about which page is being loaded for example it would be something like this
module.exports = {
entry: {
pageOne: './src/pageOne/index.js?page=main',
but now when in index.js I log
console.log('in main', window.location.href)
it is
http://localhost:9080/#/
So I'm not able to require different router basing on this. I need some other solution.
Edit
#Daniel Lizik in comment section suggested to use environment variable. He also said to use webpack config in order to set it. Considering that I would refactor my entry object to following:
module.exports = {
entry: {
pageOne: './src/index.js',
pageTwo: './src/index.js',
pageThree: './src/index.js'
}
};
I would need to configure webpack somehow to set environment variable right after webpack imported file.
Webpack probably loop over this object and import files. Right after it read this line
pageOne: './src/index.js',
I would need to set some env variable to 'pageOne' so when index.js is executed it can check this variable and import correct router.
However I have no idea how I could achieve that.
You don't need to pass the query param in the entry point configuration. You have to pass it from the browser. Then you can parse the query param and pass it to new Router(). You can use urijs node module for parsing the query param in a clean way.
import URI from "urijs";
...
const uriObj = new URI(url);
const page = uriObj.query(true)[page] || "main";
const routerInstance = new Router(page);
In your browser you enter the url with the page param like http://localhost:9080/page=second
I'm in trouble with vue-router :) I create a simple map for router :
module.exports = {
'/': {
component: require('./views/home')
},
'/auth/login': {
component: require('./views/auth/login')
},
'/auth/register': {
component: require('./views/auth/register')
},
'/resumes': {
component: require('./views/resumes')
},
// 404 NotFound
'*': {
component: {
template: "not found"
}
}
};
And define router to vue and it works perfectly. My home page js codes :
module.exports = {
inherit: true,
template: require('./template.html'),
ready: function() {
if(this.isLoggedIn)
this.$route.router.go('/resumes');
}
};
I want to load resumes page if user logged in.
When I use it in any event or with v-link directive, it works normal.
But if I use it on ready function, it duplicates pages. It calls home page and appends second page on it.
IMG : http://imageshack.com/a/img540/9409/3DK1ZL.jpg
Whats wrong? How can I solve it? I am dealing about 4 days with this problem. Please help me guys.
this.$route.router.go('/resumes') has already been removed since Vue 2.0.