Vue 简单状态管理Store模式下无法 watch 到改变后的数据

问题:
使用 Vue 简单状态管理Store模式,组件中可以获取到 store 中的数据,
在组件中通过事件改变 store 中的值,并提交到 store 后,在 store 中可以打印出改变后的值,但在组件中通过 watch 无法监听到最新值的变化

store.js

let store = {
  state: {
    message: 'Hello!'
  },
  setMessageAction(newValue) {
    this.state.message = newValue
    console.log('store.js - newValue:', this.state.message); // 当组件改变数据后这里是可以获取到改变后的最新值的
  },
}
export default store

main.js 中引入 store

// 简单 store 模式
import store from './store'
Vue.prototype.$store = store

组件中使用 store

<template>
  <div>
    <hr>
    <h1>{{message}}</h1>
    <button @click="change">change Store</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: ''
    }
  },
  created() {
    this.message = this.$store.state.message
  },
  watch: {
    '$store.state.message': function (newVal) { // watch 无法获取组件改变后的新值
      console.log(newVal);
      console.log(this.$store.state.message);
    }
  },
  methods: {
    change() {
      this.$store.setMessageAction('change hello world')
    }
  },
}
</script>

============================== 分割线 ===================================

在 asseek 和 夕水 的提示下已经解决问题,下面是我实现的方法,有更好的方法请指出,谢谢:

两种解决方案:

  1. 使用 Vue.observable
    在组件中可以直接调用 state 中的某个值
  2. 引用 store.state 对象
    组件中使用需要先把 state 赋值给组件中 data 选项

解决方案1:

修改 store.js 如下:
state 用 observable 定义来实现响应式

let store = {
  state: Vue.observable({
    message: 'Hello!'
  }),
  setMessageAction(newValue) {
    this.state.message = newValue
    console.log('store.js - newValue:', this.state.message);
  },
}
export default store

组件调用:

<template>
  <div>
    <hr>
    <h1>{{msg}}</h1>
    <button @click="change">change Store</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      num: 0
    }
  },
  computed: {
    msg() {
      return this.$store.state.message;
    }
  },
  methods: {
    change() {
      this.$store.setMessageAction(this.num++)
    }
  },
}
</script>

解决方案2:

store.js

let store = {
  state: {
    message: 'Hello!'
  },
  setMessageAction(newValue) {
    this.state.message = newValue
    console.log('store.js - newValue:', this.state.message);
  },
}
export default store

组件:

<template>
  <div>
    <hr>
    <h1>{{msg}}</h1>
    <button @click="change">change Store</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      state: '',
      num: 0
    }
  },
  created() {
    // 注意:这里需要赋值 state 对象,而不能直接赋值对象中的某个值,否则不能触发响应式
    this.state = this.$store.state 
  },
  computed: {
    msg() {
      return this.$store.state.message;
    }
  },
  methods: {
    change() {
      this.$store.setMessageAction(this.num++)
    }
  },
}
</script>
阅读 9.1k
3 个回答

你的store.js只是个暴露个普通对象,是什么原因让你认为它是响应式的会被watch
你可以把state的数据用 Vue.observable 来处理一下,应该是可以的,没这么玩过,未实测

不能这样监听,你可以用计算属性来表示,

computed:{
    msg(){
        //msg就是动态的
        return this.$store.state.message;
    }
}

没这么玩过 vuex提供的语法糖干嘛不用

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题