我有一个简单的注册页面:
<template>
<div class="login">
<div class="login-content">
<h1 @click="redirect('/')">Logo</h1>
</div>
<div class="login-header">
<p class="paragraph-small right">Already have account?
<span class="paragraph-small pointer link" @click="redirect('/login')">Log in!</span>
</p>
</div>
<div class="login-inputs">
<div class="login-inputs-container">
<h1>Sign up</h1>
<Input :error="error" :title="'Email'" :type="'email'" :value="email" />
<Input :error="error" :title="'Password'" :type="'password'" :value="password" />
<Input :error="error" :title="'Repeat password'" :type="'password'" :styles="'padding-bottom: 10px'" :value="passwordRepeat" />
<Checkbox :value="tac" :label="`I have read and accepted <a href='/'>terms and conditions.</a>`" />
<Button :label="'Sign up'" :clickon="register" />
<p v-if="error">Passwords have to match!</p>
</div>
</div>
</div>
</template>
<script>
import { register } from "~/api";
import { mapGetters, mapState, mapActions, mapMutations } from 'vuex';
import Input from "~/components/Input";
import Button from "~/components/Button";
import Checkbox from "~/components/Checkbox";
export default {
name: "register",
components: {
Input,
Button,
Checkbox
},
watch: {
password() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) },
passwordRepeat() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) }
},
computed: {
...mapGetters({
email: 'register/getEmail',
password: 'register/getPassword',
passwordRepeat: 'register/getPasswordRepeat',
status: 'register/getStatus',
error: 'register/getError',
tac: 'register/getTac'
})
},
methods: {
redirect(path) {
this.$router.push({ path })
},
async register() {
console.log(this.tac, this.password, this.passwordRepeat, this.email)
}
}
}
</script>
<style lang="scss">
@import "../assets/css/login";
</style>
如您所见,有4个字段需要更改值—3个Input
和1个Checkbox
。当我提供数据并点击控制台中的按钮时,我得到了默认值,我试图用突变和操作做一些事情,但它不起作用。
这可能是因为我使用了我的组件,而不是默认的吗?
此外,这是我的商店store/register.js
export const state = () => ({
email: null,
password: null,
passwordRepeat: null,
status: null,
error: false,
tac: false
})
export const mutations = {
setEmail(state, value) { state.email = value },
setPassword(state, value) { state.password = value },
setPasswordRepeat(state, value) { state.passwordRepeat = value },
setStatus(state, value) { state.status = value },
setError(state, value) { state.error = value },
setTac(state, value) { state.tac = value }
}
export const actions = {
fetchEmail(ctx, value) { ctx.commit('setEmail', value) },
fetchPassword(ctx, value) { ctx.commit('setPassword', value) },
fetchPasswordRepeat(ctx, value) { ctx.commit('setPasswordRepeat', value) },
fetchStatus(ctx, value) { ctx.commit('setStatus', value) },
fetchError(ctx, value) { ctx.commit('setError', value) },
fetchTac(ctx, value) { ctx.commit('setTac', value) },
}
export const getters = {
getEmail(state) { return state.email },
getPassword(state) { return state.password },
getPasswordRepeat(state) { return state.passwordRepeat },
getStatus(state) { return state.status },
getError(state) { return state.error },
getTac(state) { return state.tac },
}
若问题是我使用的不是默认标签,而是我的组件和道具,这里是Checkbox
组件:
<template>
<div class="checkbox-container">
<label class="container">
<input type="checkbox" :value="innerValue" @input="onInput">
<span class="checkmark"></span>
</label>
<p class="checkbox-paragraph" v-html="label" />
</div>
</template>
<script>
export default {
props: {
label: {
type: String,
default: ''
},
value: {
type: Boolean,
default: false
}
},
name: "Checkbox",
watch: {
value(value) {
this.innerValue = value
},
innerValue(value) {
this.$emit('input', value)
}
},
data() {
return {
innerValue: this.value
}
},
methods: {
onInput() {
this.$nextTick(() => {
this.innerValue = !this.innerValue
})
}
}
}
</script>
一种可以帮助您更改复选框值的方法如下。
复选框组件:
<template>
<div class="checkbox-container">
<label class="container">
<input type="checkbox" @change="$emit('checkbox', value)" />
<span class="checkmark"></span>
</label>
</div>
</template>
<script>
export default {
name: 'Checkbox',
data() {
return {
value: false,
}
},
}
</script>
现在,在您的注册页面中,您可以使用模板中的复选框组件,如下所示:
<Checkbox @checkbox="checkboxChanged" />
现在在同一页和方法部分添加此方法:
checkboxChanged(event) {
this.$store.dispatch('register/fetchTac', event)
},
},
这样,当复选框的值更改时,您也可以在存储中拥有更改后的值,并使用mapGetter获取它。你可以对你的输入做同样的事情。
好吧,这是我的工作答案,我真的不知道它是否正确,但它不包含任何错误或警告:
<template>
<div class="login">
<div class="login-content">
<h1 @click="redirect('/')">Logo</h1>
</div>
<div class="login-header">
<p class="paragraph-small right">Already have account?
<span class="paragraph-small pointer link" @click="redirect('/login')">Log in!</span>
</p>
</div>
<div class="login-inputs">
<div class="login-inputs-container">
<h1>Sign up</h1>
<Input :error="error" :title="'Email'" :type="'email'" v-model="email" />
<Input :error="error" :title="'Password'" :type="'password'" v-model="password" />
<Input :error="error" :title="'Repeat password'" :type="'password'" :styles="'padding-bottom: 10px'" v-model="passwordRepeat" />
<Checkbox v-model="tac" :label="`I have read and accepted <a href='/'>terms and conditions.</a>`" />
<Button :label="'Sign up'" :clickon="register" />
<p v-if="error">Passwords have to match!</p>
</div>
</div>
</div>
</template>
<script>
import { register } from "~/api";
import { mapGetters, mapState, mapActions, mapMutations } from 'vuex';
import Input from "~/components/Input";
import Button from "~/components/Button";
import Checkbox from "~/components/Checkbox";
export default {
name: "register",
components: {
Input,
Button,
Checkbox
},
watch: {
...mapActions(['fetchTac', 'fetchError', 'fetchStatus', 'fetchPasswordRepeat', 'fetchPassword', 'fetchEmail']),
password() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) },
passwordRepeat() { this.error = (this.password !== this.passwordRepeat) && (this.password !== null && this.passwordRepeat !== null) }
},
computed: mapGetters(['getError', 'getEmail', 'getPassword', 'getPasswordRepeat', 'getStatus', 'getTac']),
data() {
return {
email: null,
password: null,
passwordRepeat: null,
status: null,
error: false,
tac: false
}
},
methods: {
redirect(path) {
this.$router.push({ path })
},
async register() {
console.log(this.passwordRepeat, this.password, this.email, this.tac)
}
}
}
</script>
但我仍然有一个问题,正如你所看到的,我同时有getter和数据,我实际上可以删除数据,但这会引起这样的警告:
Property or method "propname" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property
它会起作用,但我会得到警告。
编辑
我用这种方式解决了这个问题:
computed: {
error: {
get() { return this.$store.getters.getError },
set(value) { this.$store.commit('setError', value) }
},
email: {
get() { return this.$store.getters.getEmail },
set(value) { this.$store.commit('setEmail', value) }
},
password: {
get() { return this.$store.getters.getPassword },
set(value) { this.$store.commit('setPassword', value) }
},
passwordRepeat: {
get() { return this.$store.getters.getPasswordRepeat },
set(value) { this.$store.commit('setPasswordRepeat', value) }
},
status: {
get() { return this.$store.getters.getStatus },
set(value) { this.$store.commit('setStatus', value) }
},
tac: {
get() { return this.$store.getters.getError },
set(value) { this.$store.commit('setTac', value) }
}
},
// data() {
// return {
// email: null,
// password: null,
// passwordRepeat: null,
// status: null,
// error: false,
// tac: false
// }
// },