javascript 嵌套输入组件上的Vue3v模型绑定

beq87vna  于 12个月前  发布在  Java
关注(0)|答案(1)|浏览(91)

我正在尝试将我的组件迁移到Vue 3中。我发现在如何设置V模型上很混乱,尤其是在嵌套组件上。最初,该复选框不应该被选中,因为我正在从API中检索一个值。我应该在哪里初始设置这个嵌套组件的v-model?

CheckboxFieldComponent.vue

<template>
    <div v-show="isVisible">
      <FormCheckbox
        v-model="booleanFromStoreConvertedToArray"
        :input-value="field.model.itemId"
        :title="title"
        :id="field.valueField.id"
        :class="field.model.cssClass"
        :name="field.valueField.name"
        :checked="true"
        :required="required"
        :disabled="!isEnabled"
        @input="
          onInput(value);
          $emit('change');
        "
        @focus="field.tracker.onFocusField(field, value)"
        @blur="field.tracker.onBlurField(field, value, errors.value)"
      />
    </div>
</template>

<script>
export default {
  extends: BaseField,
  computed: {
    booleanFromStoreConvertedToArray: {
      get() {
        const isSelected = this.value;
        if (isSelected) {
          return [this.field.model.itemId];
        }
        return [];
      },
      set(value) {
        this.value = value.length > 0;
      },
    },
  },
};
</script>
FormCheckbox.vue
<template>
  <FormCheckboxBase
    :checked="shouldBeChecked"
    type="checkbox"
    :class="$style.check"
    :input-value="inputValue"
    :title="title"
    :id="id"
    :name="name"
    :required="required"
    v-bind="$attrs"
    @updateInput="updateInput"
  />
</template>

<script>
export default {
  components: {
    FormCheckboxBase,
  },
  props: {
    value: {
      type: Array,
      default: () => [],
    },
    inputValue: {
      // this is the value that will be assigned to the html element's value-property
      type: String,
      required: true,
    },
    title: {
      type: String,
      required: true,
    },
    id: {
      type: String,
      required: true,
    },
    name: {
      type: String,
      default: '',
    },
    required: {
      type: Boolean,
      default: false,
    },
  },
  computed: {
    shouldBeChecked() {
      if (!this.value) {
        return false;
      }
      return this.value.includes(this.inputValue);
    },
  },
  methods: {
    updateInput(event) {
      const { checked, value } = event.target;
      const newValue = [...this.value];
      let checkLabel;

      if (checked) {
        checkLabel = 'on';
        newValue.push(value);
      } else {
        checkLabel = 'off';
        newValue.splice(newValue.indexOf(value), 1);
      }

      // this.$emit('input', newValue); <--- This is from Vue 2 which was working
    },
  },
};
</script>
FormCheckboxBase.vue

<template>
  <div :class="$style['form-item']">
    <input
      :id="id"
      :value="inputValue"
      @change="updateInput"
      :type="type"
      v-bind="$attrs"
      class="input"
      :class="$style.input"
    />
    <slot />
  </div>
</template>

<script>
export default {
  props: {
    type: {
      type: String,
      default: 'checkbox',
    },
    inputValue: {
      type: String,
      required: true,
    },
    title: {
      type: String,
      required: true,
    },
    id: {
      type: String,
      required: true,
    },
    required: {
      type: Boolean,
      default: false,
    },
    checkboxList: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    updateInput(event) {
      // this.$emit('updateInput', event); <--- This is From Vue2 Event Emitter
    },
  },
};
</script>

我只是使用这个Basefield作为扩展组件,这样我就可以触发onInput事件,当我触发check / input字段时,它会触发两次,并且不会更改值

BaseField.vue

onInput(value) {
   this.value = value;
   // validate
   this.validate();
},
mwngjboj

mwngjboj1#

如何在组件上执行v-model?

根据official document,组件上的v-model将扩展为:

<CustomInput
  :model-value="searchText"
  @update:model-value="newValue => searchText = newValue"
/>

因此,如果在FormCheckbox上设置v-model,则必须将modelValue设置为prop以获取绑定值,并将$emitupdate:modelValue设置为双向绑定。
FormCheckbox.vue 中更改:

props: {
  value: {
    type: Array,
    default: () => [],
  },
  ...
}

收件人:

props: {
  modelValue: {
    type: Array,
    default: () => [],
  },
  ...
}

复选框嵌套绑定问题

FormCheckboxBase.vue 中,如果<input>的类型为checkbox,则v-bind:value不会应用于checked。你必须在 FormCheckboxBase.vue 中设置v-bind:check

<template>
  <div>
    <input
      :id="id"
      :type="type"
      :checked="checked"
      :required="required"
      :value="inputValue"
      v-bind="$attrs"
      @change="updateInput"
    />
  <slot />
  </div>
</template>

为什么事件被触发两次?

如果您在FormCheckbox上设置@input,则当复选框checked更改时将触发。但是,CheckboxFieldComponent.vue 中的this.value直到@change被触发才被更改。(onInput将早于onChanged触发。)
此外,this.value将由booleanFromStoreConvertedToArray的设置器设置。这意味着您还在此v-model中完成了this.value的双向绑定。
所以你只需要在booleanFromStoreConvertedToArray的setter下进行验证:

booleanFromStoreConvertedToArray: {
  get() {
    const isSelected = this.value;
    if (isSelected) {
      return [this.field.model.itemId];
    }
    return [];
  },
  set(value) {
    this.value = value.length > 0;
    // do anything you want after setting this.value
    this.validate();
  }
}

下面是演示:https://codesandbox.io/s/question-77194739-f9wm4g
希望能帮上忙!

相关问题