vue-mc icon indicating copy to clipboard operation
vue-mc copied to clipboard

Difference from Vuex

Open AlgoTrader opened this issue 6 years ago • 17 comments

Can you please explain why to prefer vue-mc over vuex?

AlgoTrader avatar Oct 23 '17 09:10 AlgoTrader

Eagerly Waiting for the answer :)

IamManchanda avatar Oct 23 '17 19:10 IamManchanda

I think you misunderstood the scope of this library. You can use Vuex with these models and collections. Basically, these classes add an useful interface to our models and collections, validation and such. Vuex is just for state management

Frondor avatar Oct 23 '17 20:10 Frondor

So, you would us collections and models in your store instead of plain objects? Do you do that yourself, or is that just in theory? It seems like there is some overlap in use-case. I would worry using both would be adding an extra layer of complexity to already complex vuex.

incraigulous avatar Oct 24 '17 01:10 incraigulous

I'm currently trying to combine vue-mc and vuex and I am having a hard time wrapping my head around this too. In each vuex module, I would like to have a standard way of communicating with the api. I also want to have a clear/active/saved state. So vue-mc offers some things that I need.

I could put the collection in vuex state and use the class interface to fetch/save. But in vuex, we can only change state with commits. So in a vuex action, I could call the .fetch and when the promise returns, I can commit the new data.

So to update some data, I think it should:

  • bind the ui field to the active state
  • when the save button is clicked, call the vuex save action, which calls the model save action
  • when the promise returns, commit the new state

But still, it feels like there's a bit too much overlap. When using Vuex, I think only Vuex modules should access the API and UI components shouldn't. They just call Vuex actions. So I'd still have to define my own Vuex actions and commits for each endpoint and I still don't have a standard api interface. I'm still writing wrappers around vue-mc functions, which gives me room to do it slightly different for each module. The default state of vue-mc also potentially overlaps with vuex initial state.

So to me it seems that this is a very nice library for direct api communication for front end components, but when used in combination with Vuex, it doesn't fit that well. It adds an extra layer that doesn't seem to do that much. Only the clear/active/saved management is perhaps enough.

So based on my short investigation, I think I agree with @incraigulous. I would very much like to hear from others on how they tackled this issue and how to avoid overlap or unnecessary wrapping and extra layers.

elcojacobs avatar Oct 24 '17 10:10 elcojacobs

Probably the library is coupling too much functionality, and a better approach would be to modularize a bit some features into plugins(?) like optionally implementing validation (some people simply prefer using their own methods, since leveraging this to the library may look a bit shady), collection methods (which imho should be left to array native methods, like .filter and .find ), pagination is simple to accomplish with any array of items. Actually, I'm using Model only, since I prefer working with native arrays instead of Collection feature

Frondor avatar Oct 24 '17 11:10 Frondor

I think the docs would benefit from a section on the overlap with vuex, in what circumstances would it make sense to use both together or just this project alone.

pmackay avatar Oct 24 '17 18:10 pmackay

@pmackay very good idea. ✨

We don't currently use vuex at Figured so we're not very familiar with the overlap or interaction. Keep in mind that this was an internal library first so there's bound to be some oddities as we develop it for other use cases and projects too.

There seems to be an issue with the way the models and collections "magically" apply data and change properties. If, for example, you did a fetch in a vuex action, the fetched data will be applied to the model as soon as it's returned, having no knowledge of vuex. We could improve support for vuex by not applying the response automatically.

The first thing to know is that store.dispatch can handle Promise returned by the triggered action handler and it also returns Promise.

So we could do something like this:

// Maybe an option to indicate that we're using vuex?
model.setOption('vuex', true);

actions: {
    fetch({ commit }) {
        return model.fetch(commit);
    }
}

This might not make any sense because my understanding of vuex is very limited (have only read the docs a couple of times), but I'm sure we can find a way to make vue-mc work well with it.

rtheunissen avatar Oct 24 '17 22:10 rtheunissen

@Frondor

some people simply prefer using their own methods, since leveraging this to the library may look a bit shady

You can use your own methods. A validation method is simply a function that returns a string if the validation fails. You're also by no means required to use vue-mc's validation, and it won't be imported at all if you decide not to.

collection methods (which imho should be left to array native methods, like .filter and .find )

You can use native methods if you want, directly on the collection's models attribute, which is a native array. The collection methods is simply a syntactic alternative that you don't need to use.

rtheunissen avatar Oct 24 '17 22:10 rtheunissen

@elcojacobs

When using Vuex, I think only Vuex modules should access the API and UI components shouldn't. They just call Vuex actions.

I agree with this, anything interacting with the store should do so with actions, not on vuemc m/c directly like you would have if you weren't using vuex.

So I'd still have to define my own Vuex actions and commits for each endpoint and I still don't have a standard api interface.

At this point, yes you would still need to define actions and commits for each endpoint, which I agree is a lot of unnecessary wrapping.


I'm all in favour of providing better vuex support, we simply haven't been using vuex at Figured so we didn't design things with that in mind. But I do believe that the code is flexible enough to add better support for vuex. We should try to work backwards from what the ideal interface/API is like then see how we could implement that.

Those of you who are familiar with vuex, what would be the ideal behaviour here?

rtheunissen avatar Oct 24 '17 22:10 rtheunissen

Hey there. I'm interested in this topic. I believe that vue-mc is a very nice package and it provides me a lot of things I need. But I'm struggling with using it with vuex aswell. In my case, I ended doing just what you were mentioning, a single state to store the model attributes, and action that calls model fetch and when returned commit to set the state with the data, and a getter that returns and empty or a new model instance with the state data.

The issue I'm currently having is that is I try to change an active attribute, the change is not reflected in a binded element. An input text with v-model set to the instance.attribute, and an element rendering the attribute, when I enter a value in the input, the rendered element doesn't update. I added a listener to the change event to the instance, and the listener runs fine and shows me that the attribute is being changed.

Eitherway..., I found another package similar to vue-mc that has vuex support, vue-spine, it could be worth to check it and get some ideas on how to integrate vuex in vue-mc.

Cheers

agustindidiego avatar Oct 24 '17 22:10 agustindidiego

@rtheunissen yes but even if you use the native array in Collecions and your own validation logic, vue-mc overhead is still there. And doesn't feel right. See Laravel's Eloquent for example, it only handles the model instance, state, and queries (returning collections for many).

Frondor avatar Oct 24 '17 22:10 Frondor

@Frondor It's not overhead if you don't use it though? It's not in your code at all. The validation is a separate module, it's just not a separate package on npm. If you don't import it, there won't be overhead in your code.

rtheunissen avatar Oct 25 '17 00:10 rtheunissen

I still cannot quite understand the lib scope. models and collections store data, state is also data. Vuex does not store plain objects, it converts plain objects into vue observables (vue reactivity system). Vuex provide data store plus mutations/actions and it has much cleaner integration with vue ecosystem. I don't think Backbone style models and collections is a step forward for vue

AlgoTrader avatar Oct 25 '17 07:10 AlgoTrader

I don't think Backbone style models and collections is a step forward for vue

It's a step sideways. 😂

We developed this library to solve a problem we were facing, so the focus was always on what is practical and what works well for us (and others, potentially). It's early days and I'd like to see this library develop into something that integrates better with the Vue ecosystem - vuex included.

Vuex does not store plain objects, it converts plain objects into vue observables

Vue itself converts plain objects into observables, so Model attributes are observable too, which allows them to be reactive.

I still cannot quite understand the lib scope

It's a bit of a mixed bag, no arguments there. Maybe it does try to do too much, but for projects that are happy to submit to its conventions, it does take a care of a lot for you.

  • Data encapsulation and definition
  • Data state (active/saved)
  • Instance state (loading/saving/deleting)
  • REST
  • Validation
  • Encourages reusability and small components (logic in the m/c instead)
  • Potentially easier to test that logic?

rtheunissen avatar Oct 25 '17 20:10 rtheunissen

Just like in ts, you can define interfaces to encapsulate your model data/properties, think of this library as a wrapper to help you manipulate objects instead of using properties bound to the vue instance. I think the library is heavily inspired from eloquent (Laravel). correct me if I'm wrong. It's in the repo's description "Models and Collections for Vue". Let's try to simplify things.

minedun6 avatar Jan 17 '18 08:01 minedun6

Hey all, just thought I'd comment my troubles. The best method for storing / interacting with VueX is to store each class as JSON (using the .toJSON() method), and using a getter to take the JSON back into a new instance of your Model, for instance:

getters: {
    getCurrentUser: function(state) {
        return new User(state.user);
    }
},
mutations: {
    updateCurrentUser: function(state, user) {
        state.user = user.toJSON()
    },
}

still going through refactoring collections, but I don't seem to have a use case for storing Collections in VueX..... nevermind.

Edit:

There may also be a bug in committing the class to VueX (even with the toJSON) as you're assigning to reference rather than assigning by value. To avoid this I just added a quick clone trick:

updateUser: function(state, user) {
    state.user = Object.assign({}, user.toJSON())
},

A really nice addition to see in VueMC (that may be bad programming practice) is that it checks if the constructor argument is an instance of itself. If it is - then return itself.

new User(new User(new User({ ... })))

sifex avatar Mar 22 '18 00:03 sifex

Hi 2021 any news on using this with vuex would be nice to have in documentation

pascaldls avatar Jun 12 '21 20:06 pascaldls