在 Vue 3 中,如何使自定义组件与 v-model 一起用于复选框组? [复制]

Posted

技术标签:

【中文标题】在 Vue 3 中,如何使自定义组件与 v-model 一起用于复选框组? [复制]【英文标题】:In Vue3, how to make Custom Component work with v-model for group of checkboxs? [duplicate] 【发布时间】:2021-08-14 14:59:10 【问题描述】:

下面给出的代码您可以看到v-model 的魔力,选中/取消选中复选框后,数组checkedNames 将自动添加/删除名称。我们不需要写任何东西来从数组中推送/切片/过滤名称,对吧?

const  ref  = Vue;

const App = 
  setup () 
    const checkedNames = ref([])
    return  checkedNames 
  


Vue.createApp(App).mount("#app");
<script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>

<div id="app">
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names:  checkedNames </span>
</div>

我的问题是:如何使用自定义组件实现相同的功能?

您可以看到,在下面给出的代码 sn-ps 中,我尝试了但我不喜欢它,因为我们缺少 v-model 的魔力,而是在我的函数 addOrRemoveItem() 中处理它

提醒:在您看来,我解释得太多了 :) 抱歉。

我遵循this 教程获得了一些想法,但没有太大帮助,然后参考了 vue 官方文档here。下面是功能代码,但有点矫枉过正。

const  ref, createApp  = Vue;

const app = createApp(
  setup() 
    const itemsSelected = ref([]);
    const items = ref([
       id: '1', name: 'Jack' , 
       id: '2', name: 'John' , 
       id: '3', name: 'Mike' , 
    ]);

    const addOrRemoveItem = (itemId) => 
      const exists = itemsSelected.value.includes(itemId);

      if (exists) 
        itemsSelected.value = itemsSelected.value.filter((id) => id !== itemId);
       else 
        itemsSelected.value.push(itemId);
      
    ;

    return  
      items,
      itemsSelected,
      addOrRemoveItem,
    ;
  ,
);

app.component('custom-checkbox', 
   props: 
    item:  type: Object, default: () => () ,
    modelValue:  type: Array, default: () => [] ,
  ,
  template: `
    <div>
      <input
        type="checkbox" :value="item.id"
        @change="$emit('update:model-value', $event.target.checked)"
      >  item.name 
    </div>
    `
)

app.mount("#app");
<script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>

<div id="app">
  <div><code>itemsSelected:  itemsSelected </code></div>
 <hr />
  <custom-checkbox
    v-for="item in items"
    :key="item.id"
    :item="item"
    :model-value="itemsSelected"
    @update:model-value="addOrRemoveItem(item.id)"
  ></custom-checkbox>
</div>

如上所述,当我按照doc $emit('update:model-value', ...) 中提到的那样进行操作时,代码有点过头了$emit 的长度。

const  ref, createApp  = Vue;

const app = createApp(
  setup() 
    const itemsSelected = ref([]);
    const items = ref([
       id: '1', name: 'Jack' , 
       id: '2', name: 'John' , 
       id: '3', name: 'Mike' , 
    ]);

    const addOrRemoveItem = (itemId) => 
      const exists = itemsSelected.value.includes(itemId);

      if (exists) 
        itemsSelected.value = itemsSelected.value.filter((id) => id !== itemId);
       else 
        itemsSelected.value.push(itemId);
      
    ;

    return  
      items,
      itemsSelected,
      addOrRemoveItem,
    ;
  ,
);

app.component('custom-checkbox', 
   props: 
    item:  type: Object, default: () => () ,
  ,
  template: `
    <div>
      <input
        type="checkbox" :value="item.id"
        @change="$emit('val-updated')"
      >  item.name 
    </div>
    `
)

app.mount("#app");
<script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>

<div id="app">
  <div><code>itemsSelected:  itemsSelected </code></div>
 <hr />
  <custom-checkbox
    v-for="item in items"
    :key="item.id"
    :item="item"
    @val-updated="addOrRemoveItem(item.id)"
  ></custom-checkbox>
</div>

【问题讨论】:

我推荐阅读本教程。使用 v-model 的想法很棒。结果也很棒。 vuejs.org/v2/guide/components.html#Using-v-model-on-Components 代码也会减少(我们不需要函数来处理子组件中的值) @leonheess 不,这对我没有帮助,因为它在做同样的事情。您建议的链接有一个我的问题开始的答案:) @Syed 如果对你没有帮助,你为什么投票结束这个问题作为你/这个的副本? @MichalLevý 但是第二个和第三个不会 ping 任何人,因为他们没有制作任何 cmets。 @MichalLevý 我收到了这个问题的警告,因为提问者试图关闭另一个问题作为这个问题的副本。如果他自己决定这两个问题是相互重复的——我该反对谁?我只是翻转了副本,因为另一个问题更受欢迎而且更老。如果您能向我解释 Vue 2 与 Vue 3 之外的任何区别,我将很乐意投票重新开放自己。如果不是,我建议您将答案移至另一个问题。 【参考方案1】:

addOrRemoveItem() 方法根本不需要。只需让 checkbox 的默认 Vue v-model 逻辑来完成繁重的工作。您唯一需要做的就是使用 computed 属性作为 v-model (因为直接使用 prop 是不可能的,因为 props 不能从子组件中改变)

const 
  ref,
  createApp
 = Vue;

const app = createApp(
  setup() 
    const itemsSelected = ref([]);
    const items = ref([
        id: '1',
        name: 'Jack'
      ,
      
        id: '2',
        name: 'John'
      ,
      
        id: '3',
        name: 'Mike'
      ,
    ]);

    return 
      items,
      itemsSelected,
    ;
  ,
);

app.component('custom-checkbox', 
  props: 
    item: 
      type: Object,
      default: () => ()
    ,
    modelValue: 
      type: Array,
      required: true
    
  ,
  emits: ['update:modelValue'],
  computed: 
    model: 
      get() 
        return this.modelValue
      ,
      set(value) 
        this.$emit('update:modelValue', value)
      
    
  ,
  template: `
    <div>
      <input
        type="checkbox" :value="item.id" v-model="model"
      >  item.name 
    </div>
    `
)

app.mount("#app");
<script src="https://unpkg.com/vue@3.0.11/dist/vue.global.js"></script>

<div id="app">
  <div><code>itemsSelected:  itemsSelected </code></div>
  <hr />
  <custom-checkbox v-for="item in items" :key="item.id" :item="item" v-model="itemsSelected"></custom-checkbox>
</div>

【讨论】:

以上是关于在 Vue 3 中,如何使自定义组件与 v-model 一起用于复选框组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 configureWebpack 使自定义变量可用于组件?

如何使自定义 GUI 控件对屏幕阅读器可见?

如何使自定义 UIView 与 UINavigationBar 结合使其看起来像一个

Vue考前详细总结

如何使自定义 UIButton 变暗

如何使自定义 UIView 可访问?