最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Update prop property when vuex store changes - Stack Overflow

matteradmin7PV0评论

After a successful mutation to the vuex store (state.posts.postments) using this code, and using Vue.set so Vue can recognize the addition of an object property:

store/modules/post.js

const mutations = {
    [types.SET_POST_COMMENTS] (state, { ments, id }) {
      let post = state.posts.find(post => post._id === id)
      Vue.set(post, 'ments', ments)
    }
}

There is no update to the template or ponent. The prop post is non-reactive (I assume because even the watcher isn't triggered). I've double checked and the Vuex store for each post's ments property is successfully being updated with a ments object, but the ponent SinglePost.vue doesn't see these changes.

SinglePost.vue

export default {
  name: 'single-post',
  props: {
    'post': {
      type: Object
    }
  },
  data () {
    return {
      currPost: this.post // tried to reassign post locally
    }
  },
  puted: {
    ments() {
      return this.postments // tried to pute ments locally
    }
  },
  watch: {
    post: function(val) { // tried to watch currPost for changes
       console.log('never triggered')
       this.currPost = val 
    }
  }

Ultimately, I can just set a local var by explicitly returning ments from the store to a ponent method and setting a local ments object, but I want to use my central store (and assume there'd be a way).

SinglePost template

{{ments}} // always empty
{{post}} // doesn't reflect store Vue.set for postments
{{currPost}} // doesn't reflect store Vue.set for postments

Edit

How I'm getting posts is:

getPosts ({ mit, state, getters, dispatch, rootState }, ctx) {
  //other stuff
  APIHelper.post('/post/search', mergedPayload).then(res => {
    var results = res.data.results
    mit('SET_POSTS', posts || [])
    // where SET_POSTS is just state.posts = posts

the vuex action getPosts is called from Posts.vue ponent without returning anything since it's set by a mutation @click="getPosts(this.context)" (this works great for setting the posts)

    <div v-for="post in posts">
      <single-post :key="post._id" :post="post" context="feed" />
    </div>

After a successful mutation to the vuex store (state.posts.post.ments) using this code, and using Vue.set so Vue can recognize the addition of an object property:

store/modules/post.js

const mutations = {
    [types.SET_POST_COMMENTS] (state, { ments, id }) {
      let post = state.posts.find(post => post._id === id)
      Vue.set(post, 'ments', ments)
    }
}

There is no update to the template or ponent. The prop post is non-reactive (I assume because even the watcher isn't triggered). I've double checked and the Vuex store for each post's ments property is successfully being updated with a ments object, but the ponent SinglePost.vue doesn't see these changes.

SinglePost.vue

export default {
  name: 'single-post',
  props: {
    'post': {
      type: Object
    }
  },
  data () {
    return {
      currPost: this.post // tried to reassign post locally
    }
  },
  puted: {
    ments() {
      return this.post.ments // tried to pute ments locally
    }
  },
  watch: {
    post: function(val) { // tried to watch currPost for changes
       console.log('never triggered')
       this.currPost = val 
    }
  }

Ultimately, I can just set a local var by explicitly returning ments from the store to a ponent method and setting a local ments object, but I want to use my central store (and assume there'd be a way).

SinglePost template

{{ments}} // always empty
{{post}} // doesn't reflect store Vue.set for post.ments
{{currPost}} // doesn't reflect store Vue.set for post.ments

Edit

How I'm getting posts is:

getPosts ({ mit, state, getters, dispatch, rootState }, ctx) {
  //other stuff
  APIHelper.post('/post/search', mergedPayload).then(res => {
    var results = res.data.results
    mit('SET_POSTS', posts || [])
    // where SET_POSTS is just state.posts = posts

the vuex action getPosts is called from Posts.vue ponent without returning anything since it's set by a mutation @click="getPosts(this.context)" (this works great for setting the posts)

    <div v-for="post in posts">
      <single-post :key="post._id" :post="post" context="feed" />
    </div>
Share Improve this question edited Feb 6, 2018 at 21:36 Kyle Cureau asked Feb 6, 2018 at 19:40 Kyle CureauKyle Cureau 19.4k23 gold badges77 silver badges104 bronze badges 6
  • Can you show how you're retrieving the post object from the store and passing it to the ponent as the prop? – thanksd Commented Feb 6, 2018 at 21:18
  • @thanksd, i updated my post with an "Edit" -- basically posts (contains many post objects) are set on the store, iterated over with v-for in Posts.vue where each post is passed as a prop to SinglePost.vue (i've gotten it to work by retrieving and setting ments in SinglePost, but not using the vuex store) – Kyle Cureau Commented Feb 6, 2018 at 21:39
  • In that v-for, where / how is the data for posts being set? – thanksd Commented Feb 6, 2018 at 21:44
  • @thanksd, it's set in the SET_POSTS mutation in the vuex store with state.posts = payload called from the getPosts action. The getPosts action is dispatched by the action handler getPosts attached to a click event (@click="getPosts(this.context)") in Posts.vue — in brief, posts is set in the vuex store, not in the ponent – Kyle Cureau Commented Feb 6, 2018 at 21:59
  • I mean how are you accessing the value of those posts from your ponent? Do you have a getter set up? Are you using mapGetters? – thanksd Commented Feb 6, 2018 at 22:03
 |  Show 1 more ment

2 Answers 2

Reset to default 4

You should use vuex's mapGetters helper method.

puted: {
    ...mapGetters({
        currPost: 'GET_CURRENT_POST'
    })
},

It gives access to store state and is reactive so you won't need watchers or additional puteds.

Two-way data binding is a great way to achieve this, you can create your own getter/setter method and import it in your Vue ponents whenever you need it:

export function mapFields(fields)
{
    let puters = {}
    for (let field of fields) {
        puters[field] = {
            get() {
                return this.$store.state[field];
            },
            set(value) {
                this.$store.mit(`UPDATE_${field.toUpperCase()}`, value);
            }
        }
    }
    return puters;
}

Then in your Vue ponent:

import {mapFields} from 'utils.js'; // or whatever the name of the file

puted: {
   ...mapFields(['mappedState']),
},

Updating this.mappedState in your Vue ponent:

this.mappedState = ['foo', 'bar'];

will trigger:

this.$store.mit('UPDATE_MAPPEDSTATE', ['foo', 'bar']);

And to get the property's data just call it in your ponent:

// In your template
{{ mappedState }}

// In Vue methods
this.mappedState;
Post a comment

comment list (0)

  1. No comments so far