如何在输入的 v 模型上使用 pinia 存储 getter?

use*_*584 6 javascript vue.js vuejs3 pinia

在我的应用程序中,我正在努力存储用户表单响应。我创建了 pinia 商店并创建了每个表单对象。使用这个存储到我的组件中并将该存储的 getter 函数传递到变量中,

我将这个变量用作 v 模型。给出输入后也不会返回任何内容。我也没有收到任何错误。我是否遵循了任何错误的方法?

用户存储.js

    import { defineStore } from 'pinia';
    
    export const userResponses = {
      formsResponses: {
        form1: {
          input1: '',
        },
      },
    };
    
    export default defineStore('userStore', {
      state() { return userResponses; },
    
      getters: {
        getFormsInput: (state) => state.formsResponses.form1,
      },
      actions: {
        setFormsResponses(formResponses) {
          this.formsResponses.form1 = formResponses;
        },
      },
    });
Run Code Online (Sandbox Code Playgroud)

Form1.vue

  <template>
    <input type="text" name="input_form" v-model="input"/>
    <button type="Primary" @click="submit">submit</button>
  </template>
    
    <script setup>
    import { computed, ref } from 'vue';
    import useUserStore from '@/store/userStore';
    
    
    const userStore = useUserStore();
    
    const input = ref('');
    const responses = computed(() => userStore.getFormsInput);
    
    reponses.value.input1 = input.value;
    
    function submit() {
      console.log(reponses.value.input1); // it is giving nothing
    }
    
    </script>
Run Code Online (Sandbox Code Playgroud)

为什么我无法使用 getter 或无法更新值?我可以直接在 v-model 中使用 getter 吗?

And*_*hiu 11

有很多方法可以将存储的状态双重绑定到表单输入(直接在存储的状态、storeToRefs、toRefs 上计算的可写,或者使用存储 getter 和操作计算的可写,仅举几例)。

最短的是:

const { someState } = toRefs(useStore())
Run Code Online (Sandbox Code Playgroud)

现在您可以使用someStatewith v-model,它将直接更新商店状态。
要重命名存储状态成员并避免名称冲突:

const { 
  foo: localFoo,
  bamboo: localBamboo
} = toRefs(useStore())
// console.log(localBamboo.value)
Run Code Online (Sandbox Code Playgroud)

以上所有内容都创建了ref()s。如果在脚本中使用它们,则需要使用.value,这与在 中不同<template>,它们由 Vue 解包。


如果您想完全控制读取和写入方法(用于动态验证或转换数据),请使用可写计算(又名:计算 getter/setter):

const store = useStore()
const myInput = computed({
  get() {
    return store.someState
  },
  set(val) {
    store.someState = val
  }
})
Run Code Online (Sandbox Code Playgroud)

您在这里不需要它,但您会发现它是复杂表单的基础,特别是当您需要精细控制和自定义验证时。

上面的内容与使用 Options API 写入存储状态的方式非常接近:

  computed: {
    myInput: {
      get() { 
        return useStore().someState
      },
      set(val) { 
        useStore().someState = val
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

值得注意的是,pinia为您提供了 的替代方案toRefs,称为storeToRefs,它提供所有存储状态和 getter 作为响应ref式。我不知道它是否不仅仅是重新导出,toRefs但是,由于它来自'pinia',所以我信任它并且通常更喜欢它toRefs(尽管我没有听说过toRefs工作方式不同的情况):

const { someState } = toRefs(useStore())
Run Code Online (Sandbox Code Playgroud)

看到它工作了。输入基本上直接写入存储的状态。

如果您想将 store getter 链接到 a,v-model它必须有一个 setter(如上所示)。

注意:我显着减少了你们商店的结构。如果没有充分的理由,尽量不要让事情变得过于复杂。


如果您想要本地表单状态(并且用户应该选择何时保存/重置):

本地表格状态示例
再次删除不必要的绒毛/样板。
请注意存储状态和本地状态之间两个接触点处使用的解构。您可能认为submit任务可能是:

form1.value = localForm
Run Code Online (Sandbox Code Playgroud)

...,但是,一旦完成此操作,localForm的反应性就会附加到商店状态,并且每个用户输入都会保存在商店中,而无需submit().


相关链接:


1 - 需要使用安装程序存储语法来拥有“可写的 getter”