Does $destroy function removes the Vue Custom component from cache - vue.js

I construct deep nested tree of parent and children Vue custom components using my top level component dynamically and then I am updating the data from which all tree is constructed. Which has an effect of rendering the entire tree (its a form with various custom components). I refresh/rebuild the whole form after fetching the data (which is what vue do for reactive data) that itself tell me how to regenerate the view (its like a JSON Schema from which I render the entire view).
This is related to my other issue here.
I am observing a very weird behavior in my Vue Application. When I destroy all my children components and rebuild the data to force rendering the form, it appears that even after I have called $destroy on every child component...Vue is not entirely removing them from cache?
Does vue remove the component from cache if a $destroy is called ?
Because I do not see multiple components of the same type in the Vue component list in the Chrome Vue DevTool extension panel. But I see that the same custom event is handled twice by the same component. Same function that handle the events is getting called twice even though there is only one component visible in Vue DevTools of this type.
This only happens after I render the form. When the page is loaded for the first time every thing works. Then after I reset the form by destroying the child component and resetting the data to re-render the form, magically this child component start handling the event twice.. and in 3rd render it handle the events thrice. But I see only one component in google chrome VueJS DevTool extension panel. So my guess is that vue is still keeping the previously destroyed component in cache. I am trying to figure out how should I destroy those components in the cache.
If anyone has observed something similar and found a solution please let me know.
At the moment I am going to dig little bit more on my component keys (this particular component does not have explicit key set by me).

First and foremost, the vue documentation states:
vm.$destroy
In normal use cases you shouldn’t have to call this method yourself.
Prefer controlling the lifecycle of child components in a data-driven
fashion using v-if and v-for.
So instead of destroying and rebuilding the components manually yourself, you should really letting vue handle that via v-if and v-for. If the components aren't updating to your changes, you might be dealing with a reactivity issue.
As you mentioned that this is a deeply nested structure, the reactivity is key to keeping the components up to data with the data.
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the Vue.set(object, key, value) method:
Vue.set(vm.someObject, 'b', 2)
Inside of a component:
this.$set(this.someObject, 'b', 2)
Also, keep in mind that Vue should be doing the heavy lifting in regards to component management, while you should define the parameters by which a component is rendered.

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 render markup so there's less FLOUT with a Vue Component?

I need to render a list of items (server rendered), each item has a countdown timer. When I just have my view component in each dom element there's nothing there, then POP, the view component renders the countdown... Now I know this value on the server side as well, is there some way to render it immediately such that the vue component will takeover the rendering? (Does that make sense)
Like the html from the server renders 50:32 (minutes, seconds), but then the view component takes over, removes it and starts the countdown 50:31, 50:30... etc etc.
I've tried passing the server val in as a prop and just rendering it inside the node, still pops (I assume because the component is rendering...)
Is this even doable, or am I stuck with a loader?
Thank you for your relevant question, I propose an answer from what I understand.
you are trying to dynamically pass a property from the server to a view instance already created. This is not possible because Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the
Vue.set(object, propertyName, value) method:
Vue.set(vm.someObject, 'b', 2)
go on the official documentation of Vue to know more
here : https://v2.vuejs.org/v2/guide/reactivity.html
hope that it puts you on the right track

Vue component 'mount' on v-bind change

mount on a component does not fire for v-bind changes to the component in the root.
I have a dynamic component where I often change the value of the data referenced in v-bind:is and v-bind attributes, switching the current component and its data. This works great to show different "screens" of my application.
I have some logic that happens on mount for many of the components. However, this only gets called when the v-bind:is value is changed, but no when only the v-bind attribute is. That sort of makes sense to me, though I do need to capture either.
I'm new to Vue and there is a lot of documentation. I'm so far unable to determine if there's a built-in functionality for a callback to v-bind:is and v-bind. Can anyone help me out here?

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.

Attach/Render RactiveJS component outside of template

I've got an existing SPA that was developed using nested RactiveJS components. Which is great, and offers a ton of flexibility throughout the entire app. Currently I attempting to add in client side routing support using page. My navigation switches out high-level components using simple {{#visible}}{{/visible}} template markup on each component. This is a little troublesome in its current state as it always kicks off a re-render whenever the high-level component becomes visible again.
Is there a way to render a component, for example, called widget, without using the
<widget></widget>
method? I've already "registered" the component with the parent, but obviously when constructing it by means of
new App.components.widget
I am able to control how/when it's rendered/inserted/detached, but lose the recognition in the application's component hierarchy.
There is insert exactly for that. You don't even need to "register" it to the component you plan to put it to. You can use the different find* methods or nodes to easily retrieve a reference of your planned container element.
var instance = new YourDetachedWidget({ ... });
instance.insert('#your-container'); // This could be a node, selector or jQuery object