提问者:小点点

更新Vue中的计算属性(表单)时出错?


好的,我接着看了整个Vue Laracasts视频,最后有了一个表单和一个错误类。这里有一个github链接到视频中的回购协议:

https://github.com/laracasts/Vue-Forms/blob/master/public/js/app.js

现在我要做的是集成Vuex来跟踪我当前登录的用户,用当前值预填充表单,并在任何Laravel验证失败时显示错误。

我似乎遇到的问题是,我必须将我的AuthUser设置为计算属性,以便从Vuex存储中提取它。然后,由于我不能在任何数据集中使用这些,我不得不将表单移动到计算属性。现在它是一个计算属性,它永远不会更新,所以即使抛出错误,我的表单也不会有错误。

这是我的路线文件Account.vue

<template>
<div>
    <form @submit.prevent="onSubmit" @keydown="form.errors.clear($event.target.name)">
        <div class="row">
            <div class="form-group col-md-6 col-lg-3">
                <label>Name</label>
                <input type="text" class="form-control" name="user" autocomplete="false" v-model="form.name">
                <span class="help is-danger" v-if="form.errors.has('name')" v-text="form.errors.get('name')"></span>
            </div>
            <div class="form-group col-md-6 col-lg-3">
                <label>Email address</label>
                <input type="email" class="form-control" placeholder="Enter email" autocomplete="false" name="email" v-model="form.email">
                <span class="help is-danger" v-if="form.errors.has('email')" v-text="form.errors.get('email')"></span>
            </div>
            <div class="form-group col-lg-3">
                <label>Password</label>
                <input type="password" class="form-control" placeholder="Password" autocomplete="false" name="password" v-model="form.password">
                <span class="help is-danger" v-if="form.errors.has('password')" v-text="form.errors.get('password')"></span>
            </div>
        </div>

        <div class="col-12">
            <button type="submit" class="btn btn-primary">Submit</button>
        </div>
    </form>
</div>
</template>

<script>
export default {
    computed: {
        authUserName: {
            get: function() {
                return this.$store.getters.getAuthUser.name;
            },
            set: function(value) {
                this.$store.commit('setAuthUserValue', { key: 'name', value })
            }
        },
        authUserEmail: {
            get: function() {
                return this.$store.getters.getAuthUser.email;
            },
            set: function(value) {
                this.$store.commit('setAuthUserValue', { key: 'email', value })
            }
        },
        form() {
            return new Form({
                name: this.authUserName,
                email: this.authUserEmail,
                password: ''
            })
        }
    },

    data() {
        return {

        }
    },

    mounted() {
    },

    methods: {
        onSubmit() {
            this.form
                .patch('/current-user')
                .then(status => {
                    this.$emit('success', status);
                });
        }
    }
}
</script>

指数js

import AuthUser from "../models/AuthUser";

export default new Vuex.Store({
state: { // = data
    authUser: {
        name: null,
        email: null,
    }
},

getters: { // = computed properties
    getAuthUser(state, getters) {
        return state.authUser;
    }
},

actions: { // = methods
    fetchAuthUser(context) {
        AuthUser.load(user => {
            context.commit('setAuthUser', user);
        });
    }
},

mutations: {
    setAuthUser(state, user) {
        Vue.set(state, 'authUser', user);
    },
    setAuthUserValue(state, payload) {
        state.authUser = { ...state.authUser, payload }
    }
}
});

app.js

import router from './routes';
import Hamburger from './components/Hamburger';
import NavHeader from './components/NavHeader';
import store from "./store/index";

new Vue({

el: '#app',
components: {
    Hamburger,
    NavHeader
},

data() {
    return {

    }
},

created() {
    store.dispatch('fetchAuthUser');
},
router,
store
});

我试着和观察者乱搞,但是一切都出错了。我非常努力地使用现有的用户值预设来创建表单,并建议尝试vuex,但现在遇到了这些问题,表单现在需要计算而不是在数据中设置,所以表单现在永远不会有错误。抱歉,我一次学习所有这些新东西,哈哈。

编辑

我现在还尝试在数据中将form设置为空form对象,然后在mounted()中设置属性,但无论我如何尝试在mounted中访问authUser,我都没有定义。

mounted() {
    console.log(this.authUser);
    console.log(this.authUser.name);
    console.log(this.$store.getters.getUser.name);
},

输出。。。

{ob:Observer}

未定义

未定义

编辑2

更新了最新的代码,仍然没有将错误显示在输入下面,尽管它们确实显示在中的开发工具下。。根

在那里,它列出了姓名和电子邮件错误,如果我把它们留空。可能是因为它是双重嵌套的吗?我知道这是一个关于如何嵌套json响应的Laravel问题。

可能是该表单中的某些内容或应用程序中的类错误。js?


共1个答案

匿名用户

AuthUser.load是一个异步函数,当您在创建的钩子中执行它时,不能保证在A<-plhd--1/>创建的钩子被触发。

现在,您遇到的问题是由于您的计算属性没有setter表单类试图直接改变存储的值,这将导致控制台爆炸。

如果您为您的值提供了设置器,当您尝试写入时,您可以对传递给设置器的值作出反应,并且您可以将该值分派(或在您的情况下提交)到存储:

computed: {
   authUser: {
      get(): {
          return this.$store.getters.getUser;
      },
      set(value): {
          this.$store.commit('setUser', value)
      }
   }
}

但是等等,这还是不行!为什么?因为您将收到的值只是文本输入值,您如何知道要更新的AuthUser中的哪个属性?解决此问题的最简单方法可能是为authUser上的每个属性创建一个计算属性

computed: {
   authUserName: {
      get(): {
          return store.getters.getUser.name;
      },
      set(value): {
          this.$store.commit('setUser', { key: 'name', value })
      }
   },
   authUserEmail: {
      get(): {
          return store.getters.getUser.email;
      },
      set(value): {
          this.$store.commit('setUser', { key: 'email', value })
      }
   },
   authUserPassword: {
      get(): {
          return store.getters.getUser.password;
      },
      set(value): {
          this.$store.commit('setUser', { key: 'password', value })
      }
   }
}

现在,您可以使用每个getter实例化表单:

new Form({
    name: this.authUserName,
    email: this.authUserEmail,
    password: this.authUserPassword
})

但是,再一次,这仍然行不通!我们需要一个新的变异,它只会写入我们的authUser

setUserValue(state, payload) {
   state.authUser = { ...state.authUser, payload }
}

通过使用简单的解构,我们可以覆盖authUser的属性,并合并到计算属性的新值中。

现在,您需要更新计算属性并使用此选项$百货商店改为在setter中提交('setUserValue',{key:'name/email/password':value})

最后,您的AuthUser应该是具有预设属性的对象:

authUser: {
    name: null,
    email: null,
    password: null
}

这一点很重要,因为对象的属性是反应性的。但是,如果将属性添加到对象中,您不能简单地覆盖该对象并拥有新的被动属性。您需要使用Vue。为此设置(),例如:

setUser(state, user) {
    Vue.set(state, 'authUser', user)
}

这将正确地允许观察到的属性成为反应性的。这是VueX商店重新激活的一个重要概念。这也是为什么你的值未定义的原因。