Maybe I'm y bit too careful here. I create a component with createApp programmatically and mount it on a DOM node. Later, I remove the DOM node from the DOM tree.
Do I have to make sure to call unmount before removing the DOM node (with the mounted Vue3 app) in order to avoid a memory leak? Or is all data maintained in properties of the DOM node created during the mount? The documentation doesn't mention this explicitly (or I failed to find anything).
Explicit unmounting seems natural according to general resource allocation/deallocation rules. No need for explicit unmounting also seems natural as this is a garbage collecting environment.
Related
I'm trying to write SSR-friendly code, keeping in mind a potential migration of my app from SPA to SSR. One of the principles of such code is to avoid statefull singletons which can cause cross request state pollution
The problem comes when I need to use an instance of Vuex, Vue-router, Vue-i18n etc. outside of Vue component. Because the solution in all the respective SO answers is... You guessed it. To create and export a statefull singleton in a separate js file and then import it all over the app:
Vue-router: https://stackoverflow.com/a/43562210/11208064
Vuex: https://stackoverflow.com/a/47575742/11208064
Vue-i18n: https://stackoverflow.com/a/66695008/11208064
A simple example
// store.js
export default new Vuex.Store() {} // this is a singleton
// someOtherModule.js
import { store } from './store.js'
Pinia has covered the issue in the docs. They recommend to access the pinia instance via app.$pinia. However they don't specify how do I access the app instance itself.
Also the problem is not limited to these libraries. We write our own modules which work in a similar manner.
Researching the issue I came across this article. It suggests to wipe module cache, so each time you require it all the code is executed again, making it fresh and stateless. Sounds pretty sophisticated, but maybe this is the way? And if not, what is the recommended solution?
So I have been learning the Vue Composition API and was wondering what the difference between watchEffect and watch is. Watch says it's the same as the Vue 2 watch, so I'm guessing watchEffect is like the 2.0 of that? I'm wondering if there is any specific cases where one would have great advantages over the other like in the case of stopping the watchEffect and then reactivating it instead of using a boolean in a regular watch... or are they just basically different ways of writing the same thing.
Thanks!
Reference:
watcheffect: https://vue-composition-api-rfc.netlify.com/api.html#watcheffect
watch: https://vue-composition-api-rfc.netlify.com/api.html#watch
watchEffect seems to be a simplified watch and the main differences are
Only accepts a function
watch can accept either a function or one or more reactive properties.
Runs immediately when defined and when reactive dependencies change
watch only runs when reactive dependencies change
What helped me to understand the difference between watch and watchEffect in Vue 3 was to think about watchEffect as computed with side-effects.
The watchEffect() hook works like the computed() hook or the computed option, but instead of returning a value, you use it to trigger side-effects.
Use watch whenever you want to trigger a side-effect when a single reactive value changes.
// Triggers whenever `user` is updated.
watch(user, () => doSomething({ user: user.value, profile: profile.value }))
Use watchEffect whenever you need to watch multiple reactive values and trigger a side-effect whenever any of them is updated.
// Triggers whenever `user` *or* `profile` is updated.
watchEffect(() => doSomething({ user: user.value, profile: profile.value }))
See: watch vs. watchEffect when to use what with Vue.js
I would use:
watchEffect when I want to watch multiple reactive properties and I don't care about old values
watch when I want to watch one specific reactive properties and I may want old value
Note, above is what I would use them for, but may not be their only usage.
Also found in docs regarding the difference:
Compared to watchEffect, watch allows us to:
Perform the side effect lazily;
Be more specific about what state should trigger the watcher to re-run;
Access both the previous and current value of the watched state.
Source: https://composition-api.vuejs.org/api.html#watch
watchEffect is something introduced in Vue3 with its composition api. The reason to have both watchEffect and watch, as I understand, is to keep the semantics of watch as close as possible to that of Vue2. The birth of watchEffect, if you are interested, can be traced back to here and here
As it stands today, watchEffect is an immediate/eager watch that uses a more concise/consistent syntax (consistent with computed):
watchEffect does not accept explicit watch sources, but instead automatically figures out all the dependencies by immediately executing the callback (or effect as how it is called in the source code), similar to how computed works. Therefore watchEffect must run the effect immediately. And because of this, there is a common trap (at least I have to keep reminding myself of it constantly) when setting up watchEffect: you need to make sure that during the first execution of your watchEffect, all of the dependencies are indeed accessed. How would some dependency escape from being accessed? Watch for conditional statements.
watchEffect will run its effect immediately as mentioned above.
watchEffect is a deep watch. This is something I am not sure whether it is intended or not. If you use a reactive object inside your effect, any change on that object will cause the effect to rerun, even if the changed property is not the one you accessed or is nested.
If Vue 3 is designed from scratch or there is no concern of maintaining backward compatibility, I would imagine there will only be watchEffect
I'm trying to figure out how to test state change in a Stencil web component using jest. I'm new to testing in general and have found that you can you use Enzyme to test state change within React components but I haven't been able to figure out how to do it with a Stencil component. How would I go about doing this?
Generally, you are not recommended to test the internal logic of component (state) but test public API(props, events) instead.
But if you wish to test it anyway, I suggest you check Testing documentation on stencils original website. If by testing a component you mean test it by instantiating a component explicitly then it means you are going to test an instance of plain javascript class. So if your state variable marked as private (which is a best practice) then you will not able to compile it, since TS will throw compilation errors. So, as an option (and the only as I see now) you can make those state members public and check them in your expects().
I'm wondering what is is the importance of ready() method in polymer and what is the meaning of on-time initialization for such method and what is the differences between read() and connectedCallback() ???
The following should help.
connectedCallback can be called more than once
...
Generally all setup work in connectedCallback should be balanced with associated teardown work in disconnectedCallback; if not it usually means connectedCallback is the wrong place to do it
...
At this point it's hard to contrive general a use case where ready is the only/best place to do work, although they do come up from time to time in very specific cases.
...
ready is called only once, so work done here based on a property value may become invalidated if the property value is changed at a later point by the user
See https://github.com/Polymer/polymer/issues/4108#issuecomment-258983943
They both have the same "goal". To provide a way of doing something after the element has been placed in the dom.
ready is polymer specific while connectedCallback is in the spec.
So if you have a vanilla webcomponent only connectedCallback is available. For Polymer Elements you may still use ready (especially if you convert an element from Polymer 1)
There are however some timing differences discribed here:
https://www.polymer-project.org/2.0/docs/upgrade#custom-elements-apis
The ready callback, for one-time initialization, signals the creation
of the element's shadow DOM. In the case of class-based elements, you
need to call super.ready() before accessing the shadow tree.
The major difference between 1.x and 2.0 has to do with the timing of
initial light DOM distribution. In the v1 shady DOM polyfill, initial
distribution of children into is asynchronous (microtask) to
creating the shadowRoot, meaning distribution occurs after observers
are run and ready is called. In the Polymer 1.0 shim, initial
distribution occurred before ready.
As I am trying to play with evolutionary algorithms and building visualization tools of the process, I'd like to use VueJs with P5Js.
I have this code: (SO) Playing with Evolutionary Algorithms on Codepen.io
The problem is that Vue instance's data population does not update properly.
Here what I tried to do:
Pass the global objet Game as Vue instance's data. Then population get updated properly, but the data is so big that everything get laggy;
Populate Game.population array when declared, but it does not work: P5JS throw me an error createVector() is not defined;
Populate Game.population array in Vue instance's beforeCreate() method. It does not work neither. Giving me an other error;
Proxy Game.population by an other object Data declared globally or in Vue instance's beforeCreate() method, for curating interesting cells data (I don't need the pos attribute) and so avoiding createVector() error. It is a dead end;
Thinking about hoisting, I wondered if VueJS was initialized before P5JS run. It is the case. But I can't figure how to change that.
What is the issue here? How should I refactor my script so Vue instance's data and Game.population can be linked?
This solution isn't as pretty as throwing your Game object into the Vue instance, but it works.
Forked here: https://codepen.io/andymerskin/pen/LyoEmW
Here's what I changed:
Added a computed getter/setter for population, giving you a clean way to render the array's length in the template, and the ability to assign it in your Game loop using app.population = Game.population in your Game.doPopulatePacks routine.
Changed data.property in the Vue instance to _property to keep the naming conventions paired up for use inside the computed property. It does come with the caveat that it's no longer proxied to avoid conflicts with Vue's internal properties, since we're leaning on the computed property in the template.
(Currently, there isn't a clear convention for defining private properties in a Vue instance, even though underscores _ are the preference in JS more broadly.)
And with that, you'll see in the forked demo that your game's population stays up to date in the UI.