错误时更新 Vue 中的计算属性(表单)?
Posted
技术标签:
【中文标题】错误时更新 Vue 中的计算属性(表单)?【英文标题】:Updating a computed property (Form) in Vue on error? 【发布时间】:2018-11-22 03:03:27 【问题描述】:好的,所以我跟着整个 Vue Laracasts 视频,最终有一个 Form 和一个 Errors 类。这是视频中 repo 的 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>
index.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,但现在遇到了这些问题,现在需要计算表单而不是在数据中设置,所以表单永远不会现在有错误。抱歉,我一下子就学会了所有这些新东西哈哈。
编辑
我现在还尝试将表单设置为数据中的空表单对象,然后在mounted() 中设置属性,但无论我如何尝试在mounted 中访问authUser,我都无法定义。
mounted()
console.log(this.authUser);
console.log(this.authUser.name);
console.log(this.$store.getters.getUser.name);
,
输出...
ob:观察者
未定义
未定义
编辑 2
更新了最新代码,但仍然没有在输入下方显示错误,尽管它们确实显示在开发工具中。 根>帐户>计算>表单>错误>错误
如果我将它们留空,它会在其中列出名称和电子邮件错误。可能是因为它是双重嵌套的吗?我知道这是一个关于如何嵌套 json 响应的 Laravel 问题。
可能是 app.js 中的 Form 或 Errors 类中的某些内容?
【问题讨论】:
不应该authUser: []
是 authUser:
吗?
如果是这样,您应该在setUser
中设置其状态,使用:Vue.set(state, 'authUser', user);
改变了这两行,仍然是同样的问题。无法更新表单,因为它现在是计算属性,因为我无法将表单默认名称和电子邮件设置为存储的 authUser 名称和电子邮件而不将其设置为计算?
看看vue lifecycle diagram。而不是使用computed
属性来设置表单值,您应该使用data
,并在created
或mounted
方法(或任何其他可用方法)中从存储中分配初始值
@ljubadr hm 我试过了,通过在数据中创建一个空的表单对象,然后设置它的值。知道为什么 this.authUser.name
在挂载或创建时会未定义吗?
【参考方案1】:
AuthUser.load
是一个asynchronous
函数,当您在created
挂钩中执行它时,不能保证authUsers
值将在Account.vue
的created
设置时设置钩子被触发。
现在您遇到的问题是由于您有一个没有setter
的计算属性。 Form
类尝试 mutate the value of the store directly
,这将导致控制台爆炸。
如果您为您的值提供setter
,当您尝试写入它时,您可以对传递给setter
的值做出反应,您可以将该值发送(或在您的情况下,提交)到商店:
computed:
authUser:
get():
return this.$store.getters.getUser;
,
set(value):
this.$store.commit('setUser', value)
但是等等,这仍然行不通!为什么?因为您将收到的值只是文本输入值,您如何知道要更新AuthUser
中的哪个属性?可能最简单的解决方法是创建一个computed property for each property on the 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
的属性并合并计算属性的新值。
现在您需要更新您的computed properties
并在您的设置器中使用this.$store.commit('setUserValue', key: 'name/email/password': value)
。
最后,您的authUser
应该是具有预设属性的对象:
authUser:
name: null,
email: null,
password: null
这很重要,因为properties of an object are reactive
。但是,如果将属性添加到对象,you cannot simply overwrite the object and have new reactive properties
。为此,您需要使用Vue.set()
,例如:
setUser(state, user)
Vue.set(state, 'authUser', user)
这将正确地允许观察到的属性变为反应性。这是 VueX 商店响应性中的一个重要概念。这也是你的价值观是undefined
的原因。
【讨论】:
请记住,我不相信他将商店添加到app.js
中的基本 vue 组件中
@Derek 我现在,我已经更新了原始代码 sn-ps。
@Octoxan 我还是没看到
@Ohgodwhy 现在用最新的代码更新我的问题。不知道为什么在抛出错误时它仍然没有显示表单中的错误。我可以看到它位于帐户 > 计算 > 表单 > 错误 > 错误 > 名称下的开发工具中。将错误嵌套在错误中,将错误归咎于 Laravel。大声笑以上是关于错误时更新 Vue 中的计算属性(表单)?的主要内容,如果未能解决你的问题,请参考以下文章