admin管理员组

文章数量:1240583

In the code below I'm 2 way binding the output of a textarea into a p element, once from the ponent's internal state and once from Vuex. The Vuex state does show the initial value, but the value doesn't update as I add or delete text (as it does correctly with the 1st textarea bound to the internal data). What is the difference that is causing this issue?

Component code:

<template>
  <div>
    <div>
      <textarea name="textarea1" id="txtid" cols="40" rows="30" v-model="internal_state"></textarea>
      <p> {{ internal_state }}</p>
      <hr>

      <textarea name="textarea1" id="txtid" cols="40" rows="30" v-model="this.$store.state.vuex_state"></textarea>
      <p> {{ this.$store.state.vuex_state }}</p>
      <hr>

    </div>
  </div>
</template>

<script>

  export default {
    name: 'WriteArea',
    data () {
      return {
        internal_state: ''
      }
    },
    methods: {


    }
  }

</script>

Vuex code:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
  strict: true,
  state: {
    counter: 0,
    vuex_state: 'starting string'
  },
  getters: {
    vuex_getter1: (state) => {
      return state.vuex_string
    }
  }
})

In the code below I'm 2 way binding the output of a textarea into a p element, once from the ponent's internal state and once from Vuex. The Vuex state does show the initial value, but the value doesn't update as I add or delete text (as it does correctly with the 1st textarea bound to the internal data). What is the difference that is causing this issue?

Component code:

<template>
  <div>
    <div>
      <textarea name="textarea1" id="txtid" cols="40" rows="30" v-model="internal_state"></textarea>
      <p> {{ internal_state }}</p>
      <hr>

      <textarea name="textarea1" id="txtid" cols="40" rows="30" v-model="this.$store.state.vuex_state"></textarea>
      <p> {{ this.$store.state.vuex_state }}</p>
      <hr>

    </div>
  </div>
</template>

<script>

  export default {
    name: 'WriteArea',
    data () {
      return {
        internal_state: ''
      }
    },
    methods: {


    }
  }

</script>

Vuex code:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
  strict: true,
  state: {
    counter: 0,
    vuex_state: 'starting string'
  },
  getters: {
    vuex_getter1: (state) => {
      return state.vuex_string
    }
  }
})
Share Improve this question asked Jul 4, 2017 at 19:46 Sean DSean D 4,29213 gold badges52 silver badges98 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 10

Vuex state should be updated via a mutation. See the documentation for this exact problem. Solution is not to use v-model, but instead to bind to the :value of the textarea and then have a custom event to mutate the Vuex state on input: https://vuex.vuejs/en/forms.html

<input :value="message" @input="updateMessage">
// ...
puted: {
  ...mapState({
    message: state => state.obj.message
  })
},
methods: {
  updateMessage (e) {
    this.$store.mit('updateMessage', e.target.value)
  }
}

The other option is to create a setter and getter in the same puted property:

<input v-model="message">
// ...
puted: {
  message: {
    get () {
      return this.$store.state.obj.message
    },
    set (value) {
      this.$store.mit('updateMessage', value)
    }
  }
}

You can try to use mine library for 2 way binding vuex problem solution

https://github./yarsky-tgz/vuex-dot

Example:

<template>
  <input v-model="name"/>
  <input v-model="email"/>
  <button @click.stop="step++">next</button>
</template>

<script>
  import { takeState } from 'vuex-dot';

  export default {
    puted: {
      step: takeState('wizard.step') 
        .mit('setWizardStep')
        .map(),
      ...takeState('user')
        .expose(['name', 'email'])
        .mit('editUser')
        .map()
    }
  }
</script>

store/index.js

export default new Vuex.Store({
  state: {
    wizard: {
      step: 1
    },
    user: {
      name: 'John',
      email: '[email protected]'
    }
  },
  mutations: {
    setWizardStep(state, step) {
      state.wizard.step = step;
    },
    editUser(state, patch) {
      state.user = Object.assign({}, state.user, patch);
    }
  }
});

Using: vuex-map-fields

from vuex-map-fields repo:

Enable two-way data binding for form fields saved in a Vuex store.

Vuex Store

import Vue from 'vue'
import Vuex from 'vuex'
import { getField, updateField } from 'vuex-map-fields';

Vue.use(Vuex)

export const store = new Vuex.Store({
  strict: true,
  state: {
    counter: 0,
    vuex_state: 'starting string'
  },
  getters: {
    getField, //  Add the `getField` getter to the `getters` of your Vuex store.
    vuex_getter1: (state) => {
      return state.vuex_string
    }
  }

  mutations: {
    updateField,  // Add the `getField` getter to the `getters` of your Vuex store.
  }
})

Component code:

<template>
  <div>
    <div>
      <textarea name="textarea1" id="txtid" cols="40" rows="30" v-model="internal_state"></textarea>
      <p> {{ internal_state }}</p>
      <hr>

      <textarea name="textarea1" id="txtid" cols="40" rows="30" v-model="vuex_state"></textarea>
      <p> {{ vuex_state }}</p>
      <hr>

    </div>
  </div>
</template>

<script>
import { mapFields } from 'vuex-map-fields';

export default {
  name: 'WriteArea',
  data () {
    return {
      internal_state: ''
    }
  }, 
  puted: {
    // The `mapFields` function takes an array of
    // field names and generates corresponding
    // puted properties with getter and setter
    // functions for accessing the Vuex store.
    ...mapFields([
      'vuex_state ',
    ]),
  },
}

</script>

本文标签: javascript2 way data binding with VuexStack Overflow