what is the best way to use vue, vue-router to make a dashboard with keep-alive? - vue.js

I'm using vue2, vue-router with keep-alive to develop a dashboard. What I want to achieve is following:
page should re-fetch when login -> logout -> login other account
(use beforeRouterEnter, beforeRouterLeave to re-fetch !? or use condition to keep alive component or not !?)
but vue-router can't use vue data to check page should keep alive or not...
in HTML template, it will render and render. If there has some vuex data show directly in HTML, it will error with not have the object inside object yet ex:
user: {
plan: {
xxx: ''
}
}
sure I can give vuex data all of property init data. It can avoid this thing happen, but if the page with keep alive, it still happens...
also, I can write many v-if in the template, but I think it's not a good idea to put v-if all around the template to make sure data exist..ex:
v-if="user.plan && user.plan.xxx"
or add v-if in component root template, is that a good idea !?
use beforeMount without keeping alive, there is no problem but it's not a good user experience dashboard (when you change page, data disappear or you have already load page data but load again)
Is there anyone who really use Vue 2 and it's relative library (vuex, vue-router) to develop can tell me how you develop your SPA project !?

Related

Where does VueJS store the cached component when using keep-alive

I am looking for information on where Vue stores the cached component data when a component is wrapped in the keep-alive component. I looked at the local storage, cache storage, and session storage but I don't see anything obvious. I suspect that the cache is stored in the DOM but I was hoping that someone might know for sure or offer some clarification.
The issue I am having is that I have some Vue components that I am wrapping as web components using https://github.com/vuejs/vue-web-component-wrapper. This library is responsible for adding the keep-alive to my vue components. These components are then used inside other front end frameworks. The keep alive doesn't work as expected in this scenario, if I navigate away from the component and return the component is not restored to it's previous state. What I am expecting to happen is that navigation away from the component and returning restores the component to it's previous state as described in https://v2.vuejs.org/v2/guide/components-dynamic-async.html
After some digging around - in the implementation of keep-alive (Here).
You can see that the cache is stored locally on the component level, meaning that if the <keep-alive> is removed from the DOM it will lose its stored cache.
In theory, if you need it another way you may extend the component - create a prop like cacheName that you pass down to it. Have on mounted check if there is anything in localStorage for that prop to supplement it. Then add a watcher (deep) to watch for changes to the cache and store it in LocalStorage with the key coming for cacheName.
Some rough code of how the component may look - Here. Keep in mind that it may not be possible to get the object from Vue this way so you may need to copy the whole thing then add the code on top of it.

How to get access to template in asyncData?

I want to get access to this.$el in asyncData.
I use a database to store translations.
I want to get a list of translations that are used on the current page.
Then I will send a request to the server to receive them.
After that, I will merge it.
i18.mergeLocaleMessage( locale, message )
How to do it ?
You can access i18n with something like this, no need to access the template for this use case
asyncData ({ app }) {
console.log(app.i18n.t('Hello'))
}
Looking at the lifecycle of Nuxt, asyncData will happen before any template is generated at all, so it is impossible with asyncData.
And even if it was possible with some hacky trick, it would be a bit strange to have to look inside of your template to then have some logic for i18n fetching.
Why not getting a computed nested object and loop on this through your template, after you have fetched all of your required translations ?
Also, you're using asyncData + an API call each time ? So, for every page: you will stop the user, let him wait for the API call and then proceed ?
Latest point, if you are on your page and you hit F5, then asyncData hook will not be triggered. Just to let you know about this caveat.
Alternative solutions:
using the fetch() hook and display a loader until you have fetched all your translations, still better to not rely on the content of the template. This will work even on F5 and can produce a more smooth experience (by not blocking the navigation).
getting your i18n whole translations globally, at some point when your user's connection is idle. Rather than on per-page. Especially because you will need to handle the logic of not fetching some translations that you already have (if the user visits a page twice).

Vue.js create menu querying database

based on the following VueSchool tuto https://vueschool.io/courses/vue-router-for-everyone I'm trying to create a Vue app with a menu based on a list of applications found in an October server. I try to replace the static destinations[] by an applications[] filled from the database.
For that I use Axios and Vuex. I'm able to query the data, but I spent many hours trying to get it at the application loading, to create the menu, before the application is displayed...
I have a main.js an App.vue and a MenuApp.vue component for displaying the menu.
My problem is that my getter is always called before my mutation and that my application array is always empty when the menu is creating.
Is there a way to load and init properly all data before displaying my vue.js menu component ???
Or could I reload my menu component after the mutation ?
Thanks for help ;-)
You could use a "loading" layout, before load the main layout.
From "loading" layout, use async to load the applications list and all data you want to get before. At the end, just switch to main layout with applications list loaded.
From OctoberCMS side, I don't know how you are made the requests. But, try to use simple routes, calling router controllers, instead of using components. This will made a more direct request, and a better performance on your final project.

Implement onscreen console log component in Vue.js app

I'm building a Vue.js app that will be run on devices where I don't have access to a dev tools console, such as a game console. I've created a vue DebugPanel component that contains several tabs, one of them being a "log" to write to.
The UI is mostly working as I expect, but now I need to actually take what's in the console and have it output to the element in the component.
I'd like to use this solution of hijacking the consol.log function. This solution works great in a non-vue HTML page, but I'm having trouble with the best way to incorporate it into a Vue.js app.
The issue I'm having is that each tab section on my DebugPanel is hidden/shown based on a v-if attribute. The log element is only in the DOM when its tab element shown. So a call to document.getElementById errors.
Any thoughts on how to implement this in Vue.js?
You can just use Vuex store to pass data through all the app. And i think it would be better to use it in your app for global data.

Vue Single page app Router, what happens with the components when we change route?

Let's suppose I have a component called FirstPage, which is my default route, now FirstPage triggers an asynchronous call, with the help of an action of the vuex store, to be made each minute to a backend Api (it's triggered when the component is loaded as a route), now let's say I go to an about route that goes to an About component, is FirstPage still making the calls?
Edit:
I'm not developing an app with that yet, so I can't provide examples.
It's on my interest to know the behavior in these cases of the router, because whenever I change the route I would want to stop making the constant calls (as they won't be necessary).
The reason is that Depending on this I'd have to switch tooling for a project I have in mind.
In general, a component's instance will be destroyed when you navigate away from it. However, there are two exceptions to this ..
When you use routes with params. From the Vue Router docs
One thing to note when using routes with params is that when the user navigates from /user/foo to /user/bar, the same component instance will be reused. Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this also means that the lifecycle hooks of the component will not be called.
When you wrap your router-view component within a keep-alive element. Since the <router-view> is essentially a dynamic component.
Generally Vue does a very good job of housekeeping and cleaning up after a component's instance when it gets destroyed. But sometimes you'll have to do some manual cleanup, especially if you use some kind of external library. This is usually handled in the beforeDestroy hook of an instance's lifecycle.
In normal conditions, any logic/scripts/etc done at creation inside said component will be "purged" on the on destroy/close hooks (not only pertinent to vue but seen in lots of other tools), if there is a need to persist something then it should be in a higher scope (or other solution)
Any script written for the respective component only runs if the component is rendered in page. Once you go to about component replacing the previous component then previous script wont run.
you can make a parent component with a router-view and load in your page you always want to get loaded, so your FirstPage component, but this component should just have logic behind it, and no html because otherwise you will always see that rendered. Router-view the page you want to display the real html and stuff. I hope you get the idea, if not i could make an example for you. Goodluck.