Vuex returns 默认值,未提供 [Nuxt.js/Vuex]

Vuex returns default values, not provided [Nuxt.js/Vuex]

我有这个简单的注册页面:

<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>

但是我还有一个问题,如你所见,我同时有getters和data,我其实可以remove data,但是会出现这样的warning:

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
  //   }
  // },