Vuex-ORM 双向数据绑定无法监视嵌套对象

Vuex-ORM two-way-data binding cannot watch a nested object

这个问题与Two way data binding with Vuex-ORM 有关

我尝试使用 watchdeep 来处理这样的用户表单。

<template>
  <div id="app">
    <div style="display: inline-grid">
      <label for="text-1">Text-1: </label>
      <input name="text-1" type="text" v-model="user.name" />

      <label for="text-2">Text-2: </label>
      <input name="text-2" type="text" v-model="user.lastName" />

      <label for="text-3">Text-3: </label>
      <input name="text-3" type="text" v-model="user.birth" />

      <label for="text-4">Text-4: </label>
      <input name="text-4" type="text" v-model="user.hobby" />
    </div>
    <div>
      <h5>Result</h5>
      {{ userFromStore }}
    </div>
  </div>
</template>

<script>
import { mapGetters, mapMutations, mapActions } from "vuex";
export default {
  name: "App",
  computed: {
    ...mapGetters({
      userFromStore: "getUserFromStore",
      messageFromStore: "getMessage",
    }),
    user: function () {
      return this.userFromStore ?? {}; // basically "User.find(this.userId)" inside store getters
    },
  },
  watch: {
    user: {
      handler(value) {
        console.log('called')
      //  this.updateUser(value);
      },
      deep: true,
    },
  },
  methods: {
    ...mapActions({
      fetchUser: "fetchUser",
    }),
    ...mapMutations({
      updateUser: "updateUser",
    }),
  },
  created() {
    this.fetchUser();
  },
};
</script>

问题是无论我尝试什么,我的观察者都没有在观察。一旦数据来自 Vuex-ORM,我的组件就无法在 getters user

上观看

有人知道为什么吗?

User.find(...)returns一个模型。该模型的属性不是反应性的,即您不能对未被跟踪的项目执行双向数据绑定。因此你的观察者不会触发。

我的建议是将您的用户数据作为道具推送到可以以编程方式处理数据的组件。

或者,举例来说,您可以简单地手动处理双向绑定:

Vue.use(Vuex)

class User extends VuexORM.Model {
  static entity = 'users'

  static fields() {
    return {
      id: this.number(null),
      name: this.string(''),
      lastName: this.string(''),
      birth: this.string(''),
      hobby: this.string('')
    }
  }
}

const db = new VuexORM.Database()
db.register(User)

const store = new Vuex.Store({
  plugins: [VuexORM.install(db)]
})

User.insert({
  data: {
    id: 1,
    name: 'John',
    lastName: 'Doe',
    birth: '12/12/2012',
    hobby: 'This, that, the other'
  }
})

Vue.component('user-input', {
  props: {
    value: { type: String, required: true }
  },
  template: `<input type="text" :value="value" @input="$emit('input', $event.target.value)" placeholder="Enter text here...">`
})

new Vue({
  el: '#app',
  computed: {
    user() {
      return User.find(1)
    }
  },
  methods: {
    update(prop, value) {
      this.user.$update({
        [prop]: value
      })
    }
  }
})
<script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuex@3.6.2/dist/vuex.min.js"></script>
<script src="https://unpkg.com/@vuex-orm/core@0.36.4/dist/vuex-orm.global.prod.js"></script>

<div id="app">
  <div v-if="user" style="display: inline-grid">
    <label for="text-1">Name: </label>
    <user-input
      id="text-1"
      :value="user.name"
      @input="update('name', $event)"
    ></user-input>

    <label for="text-2">Last name: </label>
    <user-input
      id="text-2"
      :value="user.lastName"
      @input="update('lastName', $event)"
    ></user-input>

    <label for="text-3">D.O.B: </label>
    <user-input
      id="text-3"
      :value="user.birth"
      @input="update('birth', $event)"
    ></user-input>

    <label for="text-4">Hobby: </label>
    <user-input
      id="text-4"
      :value="user.hobby"
      @input="update('hobby', $event)"
    ></user-input>
  </div>
  <pre>User in store: {{ user }}</pre>
</div>