I'm using the vue 3 store to pass around values between components, in this case an image link.
store.js:
import {reactive} from "vue";
const re = reactive({})
export default {
re
}
An image link is assigned in a component:
store.re.article = '../../images/1.jpg'
and recalled in another component:
<img :src="store.re.article">
Problem now is that the store is not persistent. When I refresh the page, the image does not get loaded because the link does not exist anymore. I could use localstorage/sessionstorage but was wondering if there is a more elegant way of achieving persistant store (like in vuex for example).
This tool existed, but it's not maintained anymore. https://github.com/robinvdvleuten/vuex-persistedstate
I think you'll be fine using Session or Localstorage.
for those who use pinia there is a very recent solution being worked on:
https://github.com/prazdevs/pinia-plugin-persistedstate
Related
I am following a tutorial on udemy. But instead of using Vue 2 and Vuex I use Vue 3 and Pinia. It works almost. One thing I can't seem to fix like the writer does.
I made a child component that has a click event to delete a task in pinia. The thing is
he uses
#click="$store.dispatch('deleteTask', task.id)"
And he states that you don't need to import the vuex store etc in the child component. But when trying to do this with pinia i always get a deleteTask not defined. When importing the store in the child component it works. Is this even possible with pinia? I us:
#click.stop='useTasks.deleteTask(task.id)'
I got answer from the udemy guy. And i searched on pinia docs for more answers but it seems you always need to import the store in the child component. Not like you could doe with vuex
The import is working just fine in case I try to use the component from element-plus directly.
What I'm trying to do though, is to extend a component from element-plus library (it uses the composition api from Vue 3) and add some additional properties to my component and methods.
In Vue 2 it would look something like this:
export default {
extends: SomeComponent
}
In Vue 3 this seems to not be working anymore.
I've read about defineComponent but so far, without success implementing it.
Can someone shed me some lights? Thanks.
In order to extend a component that uses Composition API whereas another still uses Options API, we need to also do the setup, such as:
export default { extends: SomeComponent, setup: SomeComponent.setup }
I'm having a situation where I use a specific Vue component in multiple ways. Sometimes I initialize it as an SPA with new Vue({store}) and sometimes I use it from within another vue component.
E.g.
<template>
<component/>
</template>
How would I go about attaching a vuex store to the component in the above situation? Manually overriding the $store property obviously does not work and the Vue instance itself doesn't really shed any light on the matter. Is there a way to achieve this?
I've written a simple store factory which creates a new instance of the vuex store but I need a way to attach this to a component from within a vue template/comp.
Said component is complex enough to warrant vuex.
Apparently setting the $store property manually does do the trick.
this.$store = store
Introduction:
Currently the application has multiple modules that store data, for example:
- profile
- models
- products
- etc
... later components under the different routes reuse and modify store data.
The problem:
When the application is initially loaded (no matter what route, or component) it's needed that certain logic has to be executed in order to set the needed state of store.
Simple example can be:
Depending on the user's age in the profile:
1. Find a certain model in models
2. And update profile data with the values from model
There are methods like created() or mounted() during component creation, so it made me think about some sort of representational container under the parent route. But I wonder maybe there are different sort of hooks to be added on the initial application load.
You usually feed your initial data into the store from another (persistent) data storage. This can be LocalStorage or an external source (an REST API for instance).
One way of doing this is too postpone app creation until the store is populated and then proceed with app init.
You init code in main.js will look something similar to this
import store from './store'
someAsyncTask()
.then( () => {
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
})
This means that the user needs to wait until everything is loaded so presenting a static preloader (usually added in index.html) is a good option.
The solution for my problem ended up very obvious, but initially escaped my mind. Since the App (root component) is being passed to the Vue instance, all logic required for manipulating can be actually executed there during created or mounted methods.
However if you actually rely on the AJAX calls to be resolved before initialising the app the Radu Dita approach should be taken into the consideration.
I have a listing/detail use case, where the user can double-click an item in a product list, go to the detail screen to edit and then go back to the listing screen when they're done. I've already done this using the dynamic components technique described here: https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components. But now that I'm planning to use vue-router elsewhere in the application, I'd like to refactor this to use routing instead. With my dynamic components technique, I used keep-alive to ensure that when the user switched back to the list view, the same selection was present as before the edit. But it seems to me that with routing the product list component would be re-rendered, which is not what I want.
Now, it looks like router-view can be wrapped in keep-alive, which would solve one problem but introduce lots of others, as I only want that route kept alive, not all of them (and at present I'm just using a single top level router-view). Vue 2.1 has clearly done something to address this by introducing include and exclude parameters for router-view. But I don't really want to do this either, as it seems very clunky to have to declare up front in my main page all the routes which should or shouldn't use keep-alive. It would be much neater to declare whether I want keep-alive at the point I'm configuring the route (i.e., in the routes array). So what's my best option?
You can specify the route you want to keep alive , like:
<keep-alive include="home">
<router-view/>
</keep-alive>
In this case, only home route will be kept alive
Vue 3
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
Exactly as is, you don't need a Component attribute in the App.vue. Also your this'll work even if your components don't have a name property specified.
I had a similar problem and looked at Vuex but decided it would require too much changes/additions in my code to add to the project.
I found this library https://www.npmjs.com/package/vue-save-state which solved the problem for me, keeping the state of 1 component synchronized with localStorage, and it only took a few minutes and a few lines of code (all documented in the Github page of the package).
One solution without localStorage:
import {Component, Provide, Vue} from "vue-property-decorator";
#Component
export default class Counter extends Vue {
#Provide() count = 0
/**
* HERE
*/
beforeDestroy() {
Object.getPrototypeOf(this).constructor.STATE = this;
}
/**
* AND HERE
*/
beforeMount() {
const state = Object.getPrototypeOf(this).constructor.STATE;
Object.entries(state || {})
.filter(([k, v]) => /^[^$_]+$/.test(k) && typeof v !== "function")
.forEach(([k]) => this[k] = state[k]);
}
}
What seems to me is you are looking for some kind of state management. If you have data which is shared by multiple components and you want to render component in different order, but dont want to load data again for each component.
This works like following:
Vue offers a simple state management, but I will recommend to use Vuex which is a standard for state management among vue community.