vuejs / vuex

🗃️ Centralized State Management for Vue.js.
https://vuex.vuejs.org
MIT License
28.41k stars 9.57k forks source link

Am I cheating if I use computed properties with setters? #38

Closed thelinuxlich closed 8 years ago

thelinuxlich commented 8 years ago
<input v-model="message">

// ...
computed: {
  message: {
    get: function () {
      return store.state.message
    },
    set: function (newValue) {
      store.dispatch("CHANGE_MESSAGE", newValue)
    }
  }
}
//...
yyx990803 commented 8 years ago

Ha, I'd say this is pretty clever. The point is making sure all changes are explicitly recordable, and this does ensure every change to message is recorded in a mutation.

blake-newman commented 8 years ago

Id say this is a good way to incorporate flux, as long as there is no direct manipulation, so that an action can control calls to multiple mutations. +1

amanpatel commented 8 years ago

If this is encouraged, I wonder if it can be made less verbose and perhaps even part of Vuex or Vue natively. I'm thinking of a brand new vuex property declaration:

  vuex: {
    message:  {
      dispatch: "CHANGE_MESSAGE",
      // more configuration?
    }
  }

Again, probably a lot of thought needs to go in to this before it is actually incorporated. But I wanted to start the discussion. This also directly addresses a way to to work with v-model on writable computed properties.

This could also be a mixin or plugin opportunity which uses the configuration and creates the computed properties for you. Would love to hear thoughts.

yyx990803 commented 8 years ago

@amanpatel imo this could be used in certain situations, but I would not put it into core. The point being that this makes it much less explicit about what is going on. It's fine if you build your own abstraction layer on top of Vuex to make this possible (e.g. a mixin), because it fits your mental model well. But I think Vuex itself should only provide the most explicit API.

leevigraham commented 8 years ago

@thelinuxlich For anyone else interested I had a slightly different requirement where there was lots of child data attributes.

@LinusBorg Helped point me in the right direction over here: https://forum.vuejs.org/topic/1546/vuex-state-mutation-error-on-data-stored-inside-component-data/4

<template>
  <div>
    <h2>Customer Needs Analysis</h2>
    <input 
        :value="customerNeedsAnalysis.vehicleUsage" 
        v-on:input="update('vehicleUsage', $event)"
    >
    <textarea 
        :value="customerNeedsAnalysis.notes" 
        v-on:input="update('notes', $event)"
    ></textarea>
  </div>
</template>

<script>
export default {
  vuex: {
    getters: {
      customerNeedsAnalysis: state => state.quote.customerNeedsAnalysis
    },
    actions: {
      update: ({ dispatch }, attribute, e) => {
        dispatch('UPDATE_CUSTOMER_NEEDS_ANALYSIS', {[attribute]: e.target.value});
      }
    }
  }
}
</script>

screenshot

thelinuxlich commented 8 years ago

your solution is much better

leevigraham commented 8 years ago

@thelinuxlich Except for one small problem:

When I do this, it works well, but I've noticed an interesting artifact. If using the same model in more than one input, the mutation is called on all inputs when changing the input value in one. I could probably just check the value and abort if no change, but it would be nice to avoid calling the mutation on every input when a change is only made in one.

http://forum.vuejs.org/topic/2303/integrating-vuex-with-input-components-js-doesn-t-have-pointers/9

jperelli commented 7 years ago

As a workaround for that extreme corner case, maybe you can use something like _.debounce ?

minhtruong92 commented 6 years ago

@leevigraham : Your solution only work with "native control" HTML, if we use plugin (example : Vuetify) it won't work correctly.

Example with number input component :value = ... => we send value from model to component v-on:input = ... => we get user input value and set to model but if user input characters (not number) the control won't display correct match with your model

molerat619 commented 6 years ago

How does this work with nested data or arrays? Unlike @leevigraham's example, I would like to be still able to use v-model for all it's benefits and consistency.

molerat619 commented 6 years ago

P.S.: The use of two-way computed properties has been documented in the meantime.