Javascript Vuex从状态加载现有表单数据以进行编辑

Javascript Vuex从状态加载现有表单数据以进行编辑,javascript,firebase,vue.js,vuex,Javascript,Firebase,Vue.js,Vuex,我按照本教程的内容尝试学习Vue,我已经完成了,它可以工作了,但我正在努力做出一个我正在努力的改变 因此,有一个“设置”页面,其中包含用户配置文件(他们可以编辑自己的姓名等)。当“设置”/“配置文件”页面加载时,我希望表单加载其现有数据,以便他们可以修改它并按保存 它当前以占位符的形式加载,:placeholder=“userProfile.name”-我希望它只是用实际值填充表单,而不是将其作为占位符 感觉这样做应该简单得可笑,但却无法让它优雅地工作 设置.vue 这是我的商店,如果你需要的

我按照本教程的内容尝试学习Vue,我已经完成了,它可以工作了,但我正在努力做出一个我正在努力的改变

因此,有一个“设置”页面,其中包含用户配置文件(他们可以编辑自己的姓名等)。当“设置”/“配置文件”页面加载时,我希望表单加载其现有数据,以便他们可以修改它并按保存

它当前以占位符的形式加载,
:placeholder=“userProfile.name”
-我希望它只是用实际值填充表单,而不是将其作为占位符

感觉这样做应该简单得可笑,但却无法让它优雅地工作

设置.vue 这是我的商店,如果你需要的话:

store/index.js 编辑 我应该提到,此数据正在从Firebase Firestore加载到状态。看起来这只是一个计时问题,在组件上设置data()时数据并没有完全加载-我添加了一些控制台日志。

Fetching user profile.. Settings.vue?e12e:29
Setting Data... index.js?4360:75
Performing setUserProfile commit.. index.js?4360:29
Setting user profile in state, last step..

同样,我对Vue的了解还不够,还不知道如何最好地更改顺序。

有两件事需要考虑,首先,当您希望从状态板条箱getters中的变量获取值时(作为良好的vuex实践):

Vuex文件:

const store = new Vuex.Store({
  state: {
    userProfile: {},
    posts: [],
  },

  getters:{
    getUserProfile: (state) => state.userProfile
  }
塞蒂格斯 因此,要完成所需的操作,可以在装入的方法内部的data()中加载变量:

export default {
  data() {
    return {
      name: "",
      title: "",
      showSuccess: false,
    };
  },
  computed: {
    ...mapState(["getUserProfile"]),
  },

  mounted(){
   this.name = getUserProfile.name
  }

因此,如果您希望用户刷新页面时不会丢失加载的数据,则不能单独使用vuex,因为刷新页面时,vuex系统也会重新启动。如果要维护刷新页面后加载的数据,请将localstorage与vuex或类似解决方案一起使用。

因为这只是一个计时问题:

我建议您将数据值绑定到您所在州的观察者。 组件只需在每次状态更新时侦听,并相应地更新数据

export default {
  data() {
    return {
      name: "",
      title: "",
      showSuccess: false,
    };
  },
  computed: {
    ...mapState(["userProfile"]),
  },
  watch: {
    userProfile: {
      handler({ name, title }) {
        this.name = name;
        this.title = title;
      },
      deep: true, // deep is to listen to objects properly
      immediate: true // immediate so the watcher triggers right away when the component is mounted
    }
  },
  methods: {
    updateProfile() {
      this.$store.dispatch("updateProfile", {
        name: this.name !== "" ? this.name : this.userProfile.name,
        title: this.title !== "" ? this.title : this.userProfile.title,
      });
      
            /*  I just wouldn't reset the values here since they'll be updated in the watcher
      this.name = "";
      this.title = ""; */

      this.showSuccess = true;

      setTimeout(() => {
        this.showSuccess = false;
      }, 2000);
    },
  },
};
v-model
获取并设置传递给它的任何内容的值。由于要编辑状态属性,因此只要修改
的值,它就会尝试更改(也称为变异)状态属性的值。这将打破不变性原则 这里的解决方案是将计算出的属性传递给使用getter和setter的
v-model
,在这里您可以告诉组件从何处获取值以及如何更新它

默认情况下,
computed
属性是一种速记,只包含getter。基本上

computed: {
  name() {
    return this.$store.state.userProfile.name
  }
}
…可以写成:

computed: {
  name: {
    get() {
      return this.$store.state.userProfile.name
    }
  }
}
您需要添加一个setter,它提交适当的变异,以便更新状态:

computed: {
  ...mapState(["userProfile"]),
  name: {
    get() {
      return this.userProfile.name
    },
    set(val) {
      this.$store.commit('setUserProfile', {
        ...this.userProfile,
        name: val
      });
    }
  },
  title: {
    get() {
      return this.userProfile.title
    },
    set(val) {
      this.$store.commit('setUserProfile', {
        ...this.userProfile,
        title: val
      });
    }
  }
}
计算机设置器被记录下来



[1]-使用Vuex的原因是您不想让任何组件直接运行。相反,您希望他们将突变提交到状态,以便使用该数据的每个组件都能收到更改通知。如果您允许
v-model
直接更改您的数据,您将违反不变性原则,因此您的状态将不再是唯一的真相来源。

抱歉,我还应该提到,在本教程中,有一些部分它从Firebase DB获取数据(包括用户配置文件)。因此,如果我刷新页面(表单变为空白),导航到主屏幕,然后返回到配置文件页面,它将再次填充表单,而无需键入任何与问题中的解决方案相关的内容。只是我还没有足够的头脑去思考如何让它在刷新页面后进行“获取”。这就解决了问题。非常感谢您的详细解释:)
computed: {
  name() {
    return this.$store.state.userProfile.name
  }
}
computed: {
  name: {
    get() {
      return this.$store.state.userProfile.name
    }
  }
}
computed: {
  ...mapState(["userProfile"]),
  name: {
    get() {
      return this.userProfile.name
    },
    set(val) {
      this.$store.commit('setUserProfile', {
        ...this.userProfile,
        name: val
      });
    }
  },
  title: {
    get() {
      return this.userProfile.title
    },
    set(val) {
      this.$store.commit('setUserProfile', {
        ...this.userProfile,
        title: val
      });
    }
  }
}