使用Vue的v-bind语法,我们可以将许多具有不同值属性的复选框绑定到同一数组,然后该数组将包含所有选中的复选框的相应值.请参见示例:https://vuejs.org/guide/essentials/forms.html#checkbox

是否有可能通过自定义组件实现相同的功能?假设我按如下方式定义组件CheckBox.vue:

<script lang="ts" setup>
import { ref } from "vue";

const modelValue = ref(false);

const emit = defineEmits<{ "update:modelValue": [modelValue: boolean] }>();

function handle() {
  modelValue.value = !modelValue.value;

  emit("update:modelValue", modelValue.value);
}
</script>

<template>
  <label>
    <button type="button" @click="handle">
      <span v-if="modelValue">✔️</span>
    </button>
  </label>
</template>

现在,我可以使用v-model将变量与我的自定义复选框的值同步.如何才能使我还可以使用许多这样的复选框并将它们绑定到一个数组?

只需将问题中定义的组件与v-bind和数组结合使用即可完成以下操作:第一个复选框将向数组中添加一项,当单击该复选框时,该项将在truefalse之间更改.其他框对数组没有影响.在button上设置value属性不会改变此行为.

推荐答案

Vue SFC Playground

对于<input type="checkbox">,您必须使用value属性:

应用视图

<script setup>
import { ref } from 'vue'
import Checkbox from './Checkbox.vue';

const arr = ref([]);

</script>

<template>

  <checkbox v-model="arr" name="first" />
  <checkbox v-model="arr" name="second" />
  <checkbox v-model="arr" name="third" />
  <div> {{ arr }} </div>
</template>

Checkbox.vue

<script setup>
import { computed } from "vue";

const props = defineProps({name: String, modelValue: [Array, Boolean]});
const emit = defineEmits(['update:modelValue']);

const value = computed({
  get(){
    return props.modelValue?.includes?.(props.name) ?? props.modelValue;
  }, set(val){
    emit('update:modelValue', Array.isArray(props.modelValue) ? 
    props.modelValue.includes(props.name) ?  props.modelValue.filter(item => item !== props.name) : [...props.modelValue, props.name]
    : val);
}});


</script>

<template>
  <label>
    <button type="button" @click.prevent="value = !value">
      <span v-if="value">✔️</span>
      <span v-else>&nbsp;</span>
    </button>
  </label>
</template>

你可以保持Checkbox.vue就像处理一个布尔值一样简单.为此,您使用computed从绑定到复选框的对象属性中获取相同的数组:

Vue SFC Playground

应用视图

<script setup>
import { ref } from 'vue'
import Checkbox from './Checkbox.vue';

const arr = ref([]);

</script>

<template>

  <checkbox v-model="arr" value="first" />
  <checkbox v-model="arr" value="second" />
  <checkbox v-model="arr" value="third" />
  <div> {{ arr }} </div>
</template>

Checkbox.vue可以保持不变(同时处理数组和布尔值),但在下面的场景中可以简化:

<script setup>
import { computed } from "vue";

const props = defineProps({value: String, modelValue: [Array, Boolean]});
const emit = defineEmits(['update:modelValue']);

const value = computed({
  get(){
    return props.modelValue?.includes?.(props.value) ?? props.modelValue;
  }, set(val){
    emit('update:modelValue', Array.isArray(props.modelValue) ? 
    props.modelValue.includes(props.value) ?  props.modelValue.filter(item => item !== props.value) : [...props.modelValue, props.value]
    : val);
}});


</script>

<template>
  <label>
    <button type="button" @click.prevent="value = !value">
      <span v-if="value">✔️</span>
      <span v-else>&nbsp;</span>
    </button>
  </label>
</template>

Vue.js相关问答推荐

如何根据数据库中的条件在vue中创建类

Vuetify 3 - NavBar 组件占据整个视口高度

在 v-for 中定义变量有什么问题吗?

如果单元格不可见,则以编程方式打开行的编辑模式. Ag 网格,Vue.js

使用 cypress 进行 e2e 测试的 vuejs 期间出现 Webpack 错误

如何在 vuejs 中导入和使用本地 .csv 文件

Vue Table 2 - 自定义过滤器

Vue:如何将 store 与组件一起使用?

Vue cli 3项目,图像路径中的动态src不起作用

如何只查看数组中的一个对象?

为什么当我 Select 第二个输入框时音译transliteration不起作用?

store 的 Vuex Classic 模式已弃用,将在 Nuxt 3 中删除

Vuex 存储数据总是驻留在内存中?

Vue.js 拦截器

中文而不是英文的Element UI分页

了解 Nuxt.js 中的State状态和Getters:Getters不起作用

将登录页面包含在单页应用程序中是否不安全?

使用 VueJS 使用 3rd 方库打印元素

如何将单选按钮绑定到 vuex store ?

如何在 vue3 中的setup方法中发出事件?