In have a simple Vue cli app with some pages.
In Users.vue I fetch the data from an API with axios:
<script>
import axios from 'axios'
export default {
data() {
return {
users: []
}
},
mounted () {
axios
.get('https://api.github.com/users')
.then(response => (this.users = response.data))
}
}
</script>
This works fine. I can access the properties.
But how do I add axios and the mounted hook globally e.g. to App.vue and be able to access the data from the json in every component?
In order to use the data from everywhere in your application. you should save it in store. using vuex. https://vuex.vuejs.org/
another way could be fine too, in case you need the data just in user's children. you can simply pass the data by using props https://v2.vuejs.org/v2/guide/components-props.html
Related
I want to write a simple JS method that I will use both in Store GETTERS.
I created a new file: /plugins/myMethod.js and added it to nuxt.config.js (at plugins part).
Follows the content of the file:
export default ({ app }, inject) => {
// Inject $hello(msg) in Vue, context and store.
inject('exportaData', msg => console.log(`Data is: ${msg}!`))
}
I can use this method in Vue Components and in store ACTIONS, but not in Store GETTERS. I tried this.$myMethod(1) without any success.
Follows the code of store/data.js
export const getters = {
hoje: state => {
console.log('Running getter HOJE')
this.$exportaData('12345')
},
}
and in my Vue component:
<p>DATA: {{ $store.getters['datas/hoje'] }}</p>
Any idea how to access my custom method in the store getter?
Thanks
I want to get access beforeCreate() app cycle method in Nuxt and load data from localStorage to Vuex store, how can I do that?
You could use Nuxt middleware to achieve a beforeCreate() effect.
// /nuxtproject/middleware/store_check.js
export default function ({ store }) {
store.dispatch('stateModule/stateAction')
}
// /nuxtproject/pages/index.vue
export default {
components: {
Header
},
middleware: 'store_check',
}
As for loading from localStorage, you can use it with the middleware solution above provided Nuxt is running in SPA mode - because localStorage isn't natively available on Nuxt Universa/SSR mode.
Had this same problem after spending some hours and this other stackoverflow answer explains why (with alternatives)
https://stackoverflow.com/a/57512785/842834
I am using asiox/vuejs to create a webpage. However I want to compartmentalize the code more. One example is I use axios to make requests to the backend, and the data in the response is commited into vuex.
this.$axios.get('events').then((response) => {
this.$store.commit('data/populate', response.data)
})
.catch((e) => {
console.error(e)
})
I want to write a util method for this, like this.$populate.events()
I have tried creating utils inside the plugins/ directory, but they dont have access to this.$axios or this.$store
Note that I have axios and vuex imported in nuxt.config.js
How can this be achieved?
If you need the function in the context, Vue instances and maybe even
in the Vuex store, you can use the inject function, which is the
second parameter of the plugins exported function.
Injecting content into Vue instances works similar to when doing this
in standard Vue apps. The $ will be prepended automatically to the
function.
Reference
export default ({ app, store }, inject) => {
inject("populate", () => {
app.$axios
.get("events")
.then(response => {
store.commit("data/populate", response.data);
})
.catch(e => {
console.error(e);
});
});
};
app variable is context property.
The root Vue instance options that includes all your plugins. For
example, when using axios, you can get access to $axios through
context.app.$axios.
Figured it out not 5 minutes after posting ...
Basically use this nuxt guide
And replace this with app in the method you'd like to move
How can I access my store from my plugin? Console returns undefined.
import store from './store';
export default {
install(vue, opts){
Vue.myGlobalFunction = function(){
console.log(store);
}
}
}
I recently had to do this too to make a pouchDb plugin, and came up with a new way.
When you create your first Vue object, you can do this.
import PouchDb from '#/pouch_db/PouchDbPlugin'
let DefaultVue = Vue.extend({
components: {App},
store,
created () {
Vue.use(PouchDb, this.$store) // Create it by passing in the store you want to use
}
})
My plugin adds an additional store, and it's own mutations and getters.
export default {
install (Vue, store) {
store.registerModule('PouchDb', pds)
const pouchDb = new PouchDb(store)
Vue.pouchDb = pouchDb
Vue.prototype.$pouchDb = pouchDb
}
}
Inside the constructor, I store the store
class PouchDb {
constructor (store) {
this.store = store
// ... etc.
}
// ... more functions
}
And then use it in other functions
class PouchDb {
// ... constructor and other functions
async addSync (docId) {
this.store.dispatch('PouchDb/addSync', docId)
}
}
It's a bit of a cheat to pass in the store, but seems to work nicely. It's usable throughout the app like this
// Inside vuex store
Vue.pouchDb.addSync(// ...etc)
// inside component
this.$pouchDb.removeSync(// ...etc)
See official guide here where it states
A Vue.js plugin should expose an install method. The method will be called with the Vue constructor as the first argument, along with possible options:
So you can do this, very easily.
Vue.use( {
install(Vue){
Vue.prototype.$something = function (){
this.$store...etc
}
}
} )
To use, simply do this.$something() in a components methods/computed etc, or directly in the component markup as {{$something()}}
This will remove the plugin needing to know where the store actually resides, while still allowing you to utilize the store within the plugin.
This is because it will inherit the scope of whatever component utilizes it, thus providing access to all of the components instance properties, including things like $store, $router as well any of it's local properties such as computed properties, parents etc. Essentially the plugin functions as if it is directly a part of the component (eg if you used it as a mixin).
For Vue 3
Incase if you wonder, how to do it in Vue 3, You can use the following.
plugin.js
export default {
install(app) { // app instance
console.log(app.config.globalProperties.$store)
}
}
main.js
import store from './pathtostore'
import plugin from './plugin'
createApp(...).use(store).use(plugin)
When app starts, you import your store and "append" it to Vue, globally.
Now, if you use() your plugin, the first parameter of install() is always Vue itself, and in this moment Vue already has access to the store, in the install method you can simply start
install(vue, opts) {
... here your can acces to vue.$store ....
}
my files looks like this
./components/UserCreate.vue
./components/UserList.vue
./main.js
my vue instance in main.js
new Vue({
el: '#user-operations',
components: {
CreateUser,
UserList
}
});
index.html
<div id="user-operations">
<create-user></create-user>
<user-list></user-list>
</div
I want to trigger userList() method in UserList.vue when createUser() method in CreateUser.vue is triggered. Or how can i pass last_user property to UserList component from CreateUser.vue for append.
here is my create-user component [working]
https://jsfiddle.net/epp9y6vs/
here is my user-list component [working]
https://jsfiddle.net/ore3unws/
so i want the last user to be listed when createUser() is triggered
I recommend to create a service with all the methods operating user entities. It will separate your Components from the implementaton of the logic which is good because:
The Components doesn't have to know which calls they have to do to servers to retrieve data - it's better to use abstraction level
The Component will be lighter and easier for reuse
You will be able to use this logic (from the service) in several Components - exactly your problem
You have several ways to implement services:
Stateless service: then you should use mixins
Statefull service: use Vuex
Export service and import from a vue code
any javascript global object
I prefer (4). Here is an example how to do it:
In file /services/UsersService that will describe your service put all the relevant methods and expose them with export:
import axios from 'axios'
export default {
get() {
return axios.get('/api/posts)
}
}
Then in any Component that needs this methods import this service:
import UsersService from '../services/UsersService'
export default {
data() {
return {
items: []
}
},
created() {
this.fetchUsers()
},
methods: {
fetchUsers() {
return UsersService.get()
.then(response => {
this.items = response.data
})
}
}
}
Find even more about it in this question:
What's the equivalent of Angular Service in VueJS?
This solution is much better than using this.$parent.$refs.userList which suppose that this components will always stay "brothers" (will have the same parent).
You can trigger userList in CreateUser.vue by this code:
this.$parent.$refs.userList.userList()
and change your index.html:
<div id="user-operations">
<create-user></create-user>
<user-list :ref="userList"></user-list>
</div>
You can create last_user property in main.js then pass it to 2 components:
.
<div id="user-operations">
<create-user:lastUser="last_user"></create-user>
<user-list :lastUser="last_user"></user-list>
</div>