首页 > 解决方案 > Vue:我可以将插槽中的 v-model 名称绑定到子元素中的数组吗?

问题描述

今天我被要求使用插槽构建一个动态表单组件。表单组件是包含一个动态的输入列表,用户可以在包含 v-model 属性的自己的输入字段中放入。填写完最后一行后,应在其下方出现一个新的空白行。我从这个开始:

Parent.vue(注意:跳过无关代码):

<template>
  <div>
    <FormComponent><input type="text" v-model="something"/></FormComponent>
  <div>
</template>

<script>
import FormComponent from '../components/FormComponent.vue';

export default {
  components: { FormComponent },
  data() {
    return {
      something: []  // could be a list, or a string, number, Object, etc...
    };
  }
}
</script>

表单组件.vue:

<template>
  <div>
    <div v-for="(item, index) in items" :key="index">
      {{index+1}}<slot v-bind="items"></slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "FormComponent",
  data() {
    return {
      items: []
    }
  },
  props: {
    value: String,
  },
  created() {
    console.log("create newform");
  },
  watch: {
    items(oldValue, newValue) {
      if (oldValue[oldValue.length] == "" && newValue[newValue.length] != "") {
        newValue.push("");
      }
    }
  },

现在我想将 parent 中定义的 v-model 绑定到一个数组以自动生成新行,但似乎我无法从插槽中提取 v-model 值。如何将输入中的 v-model 定义的值链接到数组?

另外,如何允许动态更新列表?

标签: javascriptvue.jsvuejs2

解决方案


我猜你需要这样的东西。(它是 vue 3。只有 v-mode 系统有点不同)

表单组件:

<template>
  <div>
    <div v-for="(item, index) in items" :key="item.id">
      {{ index + 1 }}
      <slot :item="item" :input="onInput" />
    </div>
  </div>
</template>

<script>
export default {
  name: "FormComponent",

  props: {
    value: String,
    items: Array,
  },
  created() {
    console.log("create newform");
  },
  methods: {
    onInput(id, event) {
      console.log("id", id);
      console.log("event", event);
      // HERE you cant handle changing  the item and pass it up
      // this.$emit('update:items', NEW_ARRAY)
    },
  },
  watch: {
    items(oldValue, newValue) {
      if (oldValue[oldValue.length] == "" && newValue[newValue.length] != "") {
        newValue.push("");
      }
    },
  },
};
</script>

父.vue

<template>
  <div>
    <FormComponent v-model:items="something">
      <template #default="{ item, input }">
        <input type="text" :value="item.text" @input="input(item.id, $event)" />
      </template>
    </FormComponent>
  </div>
</template>


<script>
import FormComponent from "./FormComponent.vue";

export default {
  components: { FormComponent },
  data() {
    return {
      something: [
        {
          id: 1,
          text: "Good",
        },
        {
          id: 2,
          text: "Good",
        },
      ], // could be a list, or a string, number, Object, etc...
    };
  },
};
</script>

推荐阅读