0

这个问题与 Vuex-ORM 的双向数据绑定有关

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

<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

有人知道为什么吗?

4

1 回答 1

1

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

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

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

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>

于 2021-05-16T23:31:22.820 回答