I created a vue app using vuejs 2 and vuex 3.
Here is the code:
App.vue :
<template>
<div id="app">
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
<router-view></router-view>
<button v-on:click="increment">Test</button>
</div>
</template>
<script>
export default {
components: {
},
data() {
return {
}
},
methods: {
increment() {
this.$store.commit('increment')
console.log(this.$store.state.count)
}
},
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
main.js
import Vue from 'vue'
import router from './router.js'
import VueRouter from 'vue-router';
import App from './App.vue'
import Vuex from 'vuex'
import store from './store.js'
Vue.use(Vuex)
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
router: router,
store: store,
template: '<App/>',
components: { App },
render: h => h(App),
}).$mount('#app')
When I click at the button in App.vue file. it always throw error that this.$store is undefined. Did i do something wrong?
But when i add the following code in the main.js file. Everything work smoothly.
Vue.prototype.$store = store;
But did I already registered the store in Vue constructor. Why do I need that code? Can anyone show me the best way to fix it`? Thank you.
Turns out I install wrong version of vuex (v4 instead of v3). Problem solved.
Related
I'm following a Vue 2 tutorial but got stuck by this error. I've checked multiple questions before posting this one because I'm still unsure of what did I do wrong. Any input will be appreciated!
App.vue code:
<template>
<div id="app">
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
<TodoApp />
</div>
</template>
<script>
// import HelloWorld from './components/HelloWorld.vue'
import TodoApp from './components/TodoApp.vue';
export default {
name: 'App',
components: {
// HelloWorld,
TodoApp
}
}
</script>
body {
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
line-height: 1.6;
background: #e8f7f0;
}
.container {
max-width: 1100px;
margin: auto;
overflow: auto;
padding: 0 2rem;
}
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Store (index.js) code:
import Vuex from 'vuex';
import Vue from 'vue';
import TodoModule from './modules/TodoModule.js';
// Load vuex
Vue.use(Vuex);
// Create store
export default new Vuex.Store({
modules: {
TodoModule
}
});
Main.js code:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
TodoApp.vue code:
<template>
<div>
<h3>Vuex Todo App</h3>
<div class="todos">
<div class="todo" v-for="todo in allTodos" :key="todo.id">
{{ todo.title }}
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: "TodoApp",
computed: mapGetters(['allTodos'])
};
</script>
<style>
</style>
TodoModule.js code:
// import axios from "axios";
const state = {
todos: [
{
id: 1,
title: "first todo"
},
{
id: 2,
title: "second todo"
},
{
id: 3,
title: "third todo"
}
]
};
const getters = {
allTodos: state => state.todos
};
const actions = {};
const mutations = {};
export default {
state,
getters,
actions,
mutations
}
No Error on Compiler:
Error on Browser Console:
=== UPDATE ===
I still haven't fix this issue and I have tried restarting the localhost server, even my own laptop to check if it'll fix it.. no luck there.
From what I've read from answers, is it possible that this error happen because of my vue installation? Or perhaps I forgot to install something else when starting the development?
=== UPDATE 2 ===
Found the culprit, apparently my vue and vuex npm package either got corrupted or has a conflict, changing the version of vue to 2.7.8 and vuex to 3.0.1 then rerun npm i (after deleting the node_modules and package-lock.json) has fixed the issue!
Thanks for all the help!
I got the same problem while using Vue 2.
npm uninstall vuex
then
npm i vuex#3.0.1
npm install vuex by default npm installs version 4 which is not supported by Vue 2
https://github.com/vuejs/vuex/releases
Your code seems ok.
I could reproduce with no erros using TodoModule below.
const TodoModule = {
state: {
todos: [{ title: "1" }, { title: "2" }, { title: "3" }, { title: "4" }]
},
getters: {
allTodos: (state) => state.todos
}
};
export default TodoModule;
If error continues, you could check the naming on your files.
The store index.js as you said should be named as store.js.
Or perhaps restart server.
I think I might have actually done the same youtube tutorial on vuex state management but I didn't use the mapGetter helper function, instead, I used the vanilla functions of vuex for getting and setting global variables.
main.js
store: new vuex.Store({
state: {
user: {}
},
mutations: {
setUser(state, payload){
state.user = payload;
}
},
getters: {
getUser: state => state.user,
}})
any-component.js
this.user = this.$store.getters.getUser; //get
this.$store.commit("setUser", this.user); //set
I think you should change getter inTo
export default {
name: "TodoApp",
computed: mapGetters(['allTodos'])
};
===>
export default {
name: "TodoApp",
computed: {
...mapGetters(['allTodos'])
}
};
I want to emit event from "home" component to "about" component. But it throws this exception-"TypeError: Cannot read property '$emit' of undefined".
This is my "main.js"
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
export const bus = new Vue();
Vue.config.productionTip = false;
new Vue({
router,
render: h => h(App)
}).$mount("#app");
This is my "Home" component.
<template>
<div class="home">
<input
v-model="text"
class="text-input"
placeholder="Add text to your child component"
/>
<button #click="sendmsg" class="btn-add">Add message</button>
</div>
</template>
<script>
import { bus } from "../main";
export default {
name: "home",
data() {
return {
text: "",
};
},
methods: {
sendmsg() {
bus.$emit("msg", this.text);
this.text = "";
}
}
};
</script>
And this "About" component
<template>
<div class="about"></div>
</template>
<script>
import { bus } from "../main";
export default {
name: "about",
created() {
bus.$on("message", (data) => {
console.log(data);
});
}
};
</script>
Looks like a race-condition brought on by a possible circular dependency (main -> App -> Home -> main).
I would suggest moving your bus to its own module instead of main. See here for an example
// src/event-bus.js
import Vue from 'vue'
export default new Vue()
and then in Home.vue and About.vue
import bus from '#/event-bus'
Also, your About component is listening for the wrong event. Home emits "msg" but About listens for "message". They should use the same event name.
Demo ~ https://codesandbox.io/s/serverless-frog-kvtoj?file=/src/event-bus.js
It's working, but whem the components have their own view it's stop working.
App.vue
<template>
<div class="app">
<router-link to="/"> HOME</router-link>
<router-link to="/about"> About</router-link>
<router-view />
</div>
</template>
<style lang="scss">
.app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
align-items: center;
.btn-add {
width: 10vw;
}
.text-input {
width: 10vw;
}
}
</style>
index.js
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
I have tried every thing but it doesn't work for me, I provide router
setup link, but it throws me an exception
These relative modules were not found:
./AppContact.vue; in ./src/main.js
./AppHome.vue in ./src/main.js
./AppLogin.vue in ./src/main.js
./AppToolbar.vue; in ./src/main.js
Main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css' // Ensure you are using css-loader
import AppToolbar from './AppToolbar.vue;'
import AppContact from './AppContact.vue;'
import AppLogin from './AppLogin.vue';
import AppHome from './AppHome.vue';
Vue.use(Vuetify)
Vue.use(VueRouter)
Vue.config.productionTip = false
const routes =[
{path:'/',components:App},
{path:'/AppToolbar',components:AppToolbar},
{path:'/AppContact',components:AppContact},
{path:'/AppLogin',components:AppLogin},
{path:'/AppHome',components:AppHome}
];
const router = new VueRouter({
routes,
mode:'history'
});
new Vue({
el:'#app',
router,
render: h => h(App)
})
App.vue
<template>
<div id="app">
<app-toolbar></app-toolbar>
<router-view> </router-view>router-view>
<app-footer style="position:absolute;z-index:-1"></app-footer>
</div>
</template>
<script>
import AppToolbar from './components/AppToolbar'
import AppFooter from './components/AppFooter'
export default {
name: 'app',
components: {
AppToolbar,AppFooter
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
</style>
1. Remove the ; from the paths
i.e: './AppToolbar.vue;' should be './AppToolbar.vue';
2. Point to the correct directory
which I'm guessing is components
Main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css' // Ensure you are using css-loader
import AppToolbar from './components/AppToolbar.vue';
import AppContact from './components/AppContact.vue';
import AppLogin from './components/AppLogin.vue';
import AppHome from './components/AppHome.vue';
// etc...
I have tried to access to others pages via url, but those pages never loads
http://localhost:8080/users
http://localhost:8080/#/users
http://localhost:8080/home
http://localhost:8080/#/home
etc
This is my main.js file:
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router"
Vue.config.productionTip = false
Vue.use(VueRouter);
import Users from './components/Users.vue'
const Home = { template: "<p>home page</p>" };
const Index = { template: "<p>index page</p>" };
const About = { template: "<p>about page</p>" };
const routes = [
{ path: "/users", name: "users", component: Users },
{ path: "/home", name: "home", component: Home },
{ path: "/index", name: "index", component: Index },
{ path: "/about", name: "about", component: About },
];
var router = new VueRouter({
routes: routes,
mode: "history",
});
new Vue({
router: router,
render: h => h(App),
}).$mount('#app')
Does anyone know why vue-router not work?
I created this project with Vue CLI, and then I intalled npm install vue-router, basically i just added a new component in ./components/users and also modified the main.js file, and that's all.
I uploaded my project to GitHub: https://github.com/alex-developer-18x/vueapp
I ran your code and the problem is because you are not using "router-view". Go to your App.vue and add "router-view" component.
Example (Edited from your code):
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<!-- You should add this instead of <HelloWorld/> -->
<router-view></router-view>
</div>
</template>
<script>
// Remove the Hello World import here
export default {
name: 'App',
components: {
// And remove the Hello World component here
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
I am trying to make simple Vuex app and here are my files:
main.js
/* eslint-disable no-unused-vars */
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App'
import router from './router'
import BootstrapVue from 'bootstrap-vue'
// TODO make it work with css-loader, dunno why it's not working at my environment
import '../node_modules/bootstrap/dist/css/bootstrap.css'
import '../node_modules/bootstrap-vue/dist/bootstrap-vue.css'
Vue.use(BootstrapVue)
Vue.config.productionTip = false
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
isLogged: false
},
mutations: {
logIn (state) {
state.isLogged = true
},
logOut (state) {
state.isLogged = false
}
}
})
store.commit('logIn')
console.log('main', store.state.isLogged)
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
router,
components: { App },
template: '<App/>'
})
App.vue
<template>
<b-container>
<b-row align-h="center">
<b-col cols="4">
<div id="app">
<router-view/>
</div>
</b-col>
</b-row>
</b-container>
</template>
<script>
// import store from './store'
// store.commit('logOut')
console.log('app', this.$store)
export default {
// name: 'App'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Also I'm using vue-router:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '#/components/Home'
import Login from '#/components/Login'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/login',
name: 'Login',
component: Login
}
]
})
And after initializing the store in the main.js and injecting in the App.vue component the this.$store variable in App.vue is undefined; but at the same time in main.js all is okay.
Also trying to import the store from the App.vue (later I stored store in store/index.js) make new store, without changed state in main.js.
Your console.log('app', this.$store) is outside of your export default {}
And in any case, the this.$store code should be placed inside any of the following:
computed() {}
mounted()
methods: {}
At the point where you're attempting to access this.$store, this doesn't point to the Vue instance.
You can access the store in one of the life-cycle hooks for the Vue instance (e.g. created):
created() {
console.log(this.$store);
}