I need recommendation about "the right way" of vuejs layout structure.
I have header, which is the same for whole app but it (header) has one block that changes, depended on which child app I have. Currently it's a parent App.
What is the best solution for that?
multiple parent App
use header as a component with a slot
any better way ?
Accordingly vuejs recommendations, a child component should never change it's parent, instead you can use events or vuex, and then your header will behave accordingly.
https://v2.vuejs.org/v2/style-guide/#Implicit-parent-child-communication-use-with-caution
Related
I'm confused about best practices for passing data from parent to child components and modularity strategies.
As I know there are 2 ways:
Fetching data in parent component and send Array/object to the child via props
Send parent_id to the child via props and fetching data within the child component
Let's assume a use case working with a product edit view, having:
A parent component product
A child form component to edit basic product information
A child related_products component where other products can be linked/unlinked.
As per my experience, the first way works smoothly since it's all done in 1 request to the API: fetching a product object in parent component and passing through props the product itself to the form component and the nested objects to the related_products component. In addition, it can be done in beforeRouteEnter guard so the parent and all its children are shown with all the information at once. The cons I see here is that we have to send the correct object structure to the child component to avoid any error, having a strong dependency between components.
On the other hand, by sending the parent_id to every child component through props we release the parent from any logic. In this case, every child component acts as a "black box" and fetch/handles the information. The cons I see here is that we would have to perform 2 API requests for getting the product and the related products. In addition, the beforeRouteEnter is not viable at all, so we get an empty form/table until the data is retrieved.
This is not about how to code it, it's just about what's the best implementation as per your experience.
As far as my experience is concerned, 1-st way is better. Parent component acts as "smart" and you have access to it's life cycle hooks in order to trigger your api-requests, reset timers, e.t.c... I would also suggest to use vuex, as it allows you to make clean interface of communication between your parent component and "outer world", utilizing actions and getters.
With that being said, your "dumb" child component communicates with it's parent through props and emits interface. And because it is "dumb" - it's easier to test it or utilize something like "storybook".
we have to send the correct object structure to the child component to avoid any error
I guess, at the end of the day, you'll need correct object structure anyway, right? It could not be just random...
I have parent component that contains form component and detail component for created_at and updated_at in editing Product page.
Form is to edit the existing data and detail component will be next to the form.
I didn't have the detail component before so I fetch data from form component and use it in the component however I need some of the data in detail component which is the child of the parent of the form component.
So I moved the fetch axios to parent component and pass the data to both children now.
Is it better to do this way or is it better to send axios request both in form component and detail component?
The form is also used in adding new product.
My opinion is that you should fire requests from most top level possible. This way your children components (building blocks) can work independently from your current context. It's called presentational component and it's role is to output some markup. The container component feeds the data to the presentational component making the data flow go from top to the bottom nicely.
So in short, you did it right! However you should be careful, when your data changes in the edit form, then you probably want to fire the request on parent again, so that the data is updated for the whole app. This kind of flow is highly facilitated by Vuex. It serves as single source of truth (data) that your whole application can rely on.
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.
I was Vue.js now for a project and created and used a lot of components.
Now I started to have the problem of having too many eventemitters and props that I need to keep track of.
I guess to illustrate the problem the best I will use an example:
Lets say you have a main.vue and 2 or 3 Components.
One contains a button that should manipulate the other 2 components or switch them out.
Now I need to emit an event to the main.vue and then main.vue has to change a binded variable and pass props down to the other 2 components.
Alright: Now lets put the button in a component of of a component. You need to make sure that every link between a parent and a child is correct.
Now create a bit project and put a button in another components and you have to change everything.
So is there a good way to avoid this?
Something like a broadcast function so that every component is receiving the event?
Or a Manager that is handling the communication of all components?
use a flux pattern (vuex)
At first you may think that this does not really answer the question, since it deals with storage of data, and not handling of events. The flux pattern changes the architecture of your application by creating a single store (think database) that all components can read and write from. Coupled with the reactive nature of the reactive frameworks such as vue (or react), the components will react to a change in data. So instead of tightly coupling component A to D through B and C, you'd have component A listen to mutations in object X, and component D makes changes to object X. When the change happens, component A gets updated without having to listen to any of the children's $emit functions firing. At first it may seem daunting, but the investment is worthwhile.
I would like to know the best practice for implementing shared states between components in Vuejs.
Imagine situation A: you have a web app that shows a modal. The modal has the boolean state show. This state should change if the modal OK-button is clicked, but also if any part of the background is clicked, and perhaps even on some server pushed state change. Thus the modal should be able to change the state as should the parent app.
Situation B: you have a web app that shows input fields inside different components that share a common data value. If the user changes value through the field in one component, it should also update in the other. Again both should even update on a server push event.
Questions:
I am right that the correct way to go about this would be to use vuex and make the shared state a store field that is observed by and changed through emitted actions by all components / parents that need to modify that value?
Does that not introduce this kind of dangerous (since hard to handle) magic reactivity that we know from Meteor?
How to best document the flow, what depends on what?
A: For a modal component, I'd say that show should be a prop. So the parent component can control the modal whatever it wants. In this case there is no shared state at all.
The modal itself doesn't need to know anything about the server. If the prop show is true, just display the modal and vice versa.
I think the mask layer is a part of the modal, so when the mask is clicked, the modal emits an event. The parent component receives the event and can decide to hide the modal or not to.
Vue has an official modal example here (thanks #craig_h for mentioning): https://v2.vuejs.org/v2/examples/modal.html
B: Just bind the vuex state to the inputs. Nothing wrong.
Note that not all the components need to access the vuex store directly. For some pure UI components, just use props. So the parent components have the right to control them and increase flexibility.
I recommend you to read these docs:
https://facebook.github.io/react/docs/lifting-state-up.html
https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.j7ry4a3as
http://redux.js.org/docs/basics/UsageWithReact.html
Yes these are React / Redux docs. Since Vue is relatively young, react community has more documentation / articles. But both Vue and React are component-based libraries. The idea of how you design a component is basically the same.
You can also take a look at this vuex example: https://github.com/vuejs/vuex/tree/dev/examples/chat
This is a very simple example but it does use all the things I mentioned above. Emitting an event, some pure UI components...