检查所有的复选框VueJS

44

我正在以表格形式展示用户列表,每一行都有一个复选框来选择用户,复选框的值是用户的ID。所选的ID会在表格下方的一个span中显示。

当我点击表头中的“全选”复选框时,如何选择所有复选框或取消选择所有复选框? 我需要通过DOM或vue对象来实现它,我认为应该是后者,但不确定如何处理这个看似简单的任务?! 任何帮助将不胜感激!

HTML

<div id="app">
    <h4>Users</h4>
    <div>
        <table>
            <tr>
                <th>Name</th>
                <th>Select <input type="checkbox" @click="selectAll"></th>
            </tr>
            <tr v-for="user in users">
                <td>{{ user.name }}</td>
                <td><input type="checkbox" v-model="selected" value="{{ user.id }}"></td>
            </tr>
        </table>
    </div>

    <span>Selected Ids: {{ selected| json }}</span>
</div>

Javascript/Vuejs

->

Javascript/Vue.js

new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "pfeffer.matt@yahoo.com", 
            { "id": "2", "name": "Duane Metz", "email": "mohammad.ferry@yahoo.com"}, 
            { "id": "3", "name": "Myah Kris", "email": "evolkman@hotmail.com"}, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "lenora95@leannon.com"}, 
            { "id": "5", "name": "Brendon Rogahn", "email": "verlie.buckridge@yahoo.com"}
        ],
        selected: []
    },
    methods: {
        selectAll: function() {
            // ?
        }
    }
})
10个回答

84

我认为@Jeremy的答案更简洁,但它需要在每个用户对象上添加checked属性,如果数据来自API请求,这是没有意义的。

以下是不需要在用户对象中添加checked属性即可选择/取消选择所有行的有效且简洁的代码:

new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "pfeffer.matt@yahoo.com" },
            { "id": "2", "name": "Duane Metz", "email": "mohammad.ferry@yahoo.com" }, 
            { "id": "3", "name": "Myah Kris", "email": "evolkman@hotmail.com" }, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "lenora95@leannon.com" }
        ],
        selected: []
    },
    computed: {
        selectAll: {
            get: function () {
                return this.users ? this.selected.length == this.users.length : false;
            },
            set: function (value) {
                var selected = [];

                if (value) {
                    this.users.forEach(function (user) {
                        selected.push(user.id);
                    });
                }

                this.selected = selected;
            }
        }
    }
});
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
<h4>User</h4>
<div>
    <table>
        <tr>
            <th><input type="checkbox" v-model="selectAll"></th>
            <th align="left">Name</th>
        </tr>
        <tr v-for="user in users">
            <td>
                <input type="checkbox" v-model="selected" :value="user.id" number>
            </td>
            <td>{{ user.name }}</td>
        </tr>
    </table>
</div>
</div>

请注意,行复选框上的number属性是必需的,否则您必须将用户IDselectAll方法作为字符串推送,例如selected.push(user.id.toString());

我们也可以使用对象作为键。https://codepen.io/anon/pen/RJErOV?editors=1111 - fego

13

因为我认为,对于nhydock修改的答案不能被接受,所以我添加了自己的答案。

解决方案选择和选择全部。

HTML

<div id="app">
    <h4>User</h4>
        <div>
            <table>
                <tr>
                    <th>Name</th>
                    <th>Select <input type="checkbox" @click="selectAll" v-model="allSelected"></th>
                </tr>
                <tr v-for="user in users">
                    <td>{{ user.name }}</td>
                    <td><input type="checkbox" v-model="userIds" value="{{ user.id }}"></td>
                </tr>
            </table>
        </div>

        <span>Selected Ids: {{ userIds | json }}</span>
</div>

Javascript/Vuejs


JavaScript/Vue.js
new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "pfeffer.matt@yahoo.com"}, 
            { "id": "2", "name": "Duane Metz", "email": "mohammad.ferry@yahoo.com"}, 
            { "id": "3", "name": "Myah Kris", "email": "evolkman@hotmail.com"}, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "lenora95@leannon.com"}, 
            { "id": "5", "name": "Brendon Rogahn", "email": "verlie.buckridge@yahoo.com"}
        ],
        selected: [],
        allSelected: false,
        userIds: []
    },
    methods: {
        selectAll: function() {
            this.userIds = [];

            if (!this.allSelected) {
                for (user in this.users) {
                    this.userIds.push(this.users[user].id);
                }
            }
        },
    }
})

工作的演示代码:https://jsfiddle.net/okv0rgrk/3747/


1
问题:1)全选;2)取消选择一个项目。SelectAll复选框应变为未选中状态。 - duXing
@Sigma 很好的发现,我在 fiddle 中添加了一个修复,也许不是很好的解决方案,但它可以工作。随意发布您自己的解决方案。 - haakym
在selectAll方法中,应该使用“if(this.allSelected)”而不是“if(!this.allSelected)”。没有必要使用!。 - Kuldeep Singh Rathore

6
基本上和 @Rifki 的回答相同,但是要检查每个元素是否都存在于两个数组中,而不仅仅是长度。

new Vue({
  el: '#app',
  data: {
    users: [{
        "id": "1",
        "name": "Shad Jast",
        "email": "pfeffer.matt@yahoo.com"
      },
      {
        "id": "2",
        "name": "Duane Metz",
        "email": "mohammad.ferry@yahoo.com"
      },
      {
        "id": "3",
        "name": "Myah Kris",
        "email": "evolkman@hotmail.com"
      },
      {
        "id": "4",
        "name": "Dr. Kamron Wunsch",
        "email": "lenora95@leannon.com"
      }
    ],
    selected: []
  },
  computed: {
    selectAll: {
      get() {
        if (this.users && this.users.length > 0) { // A users array exists with at least one item
          let allChecked = true;

          for (const user of this.users) {
            if (!this.selected.includes(user.id)) {
              allChecked = false; // If even one is not included in array
            }
            
            // Break out of loop if mismatch already found
            if(!allChecked) break;
          }

          return allChecked;
        }

        return false;
      },
      set(value) {
        const checked = [];

        if (value) {
          this.users.forEach((user) => {
            checked.push(user.id);
          });
        }

        this.selected = checked;
      }
    },
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <h4>User</h4>
  <div>
    <table>
      <tr>
        <th><input type="checkbox" v-model="selectAll"></th>
        <th align="left">Name</th>
      </tr>
      <tr v-for="user in users">
        <td>
          <input type="checkbox" v-model="selected" :value="user.id" number>
        </td>
        <td>{{ user.name }}</td>
      </tr>
    </table>
  </div>
</div>


在取消选择父复选框时,所有子复选框都将取消选择。您能否更新您的答案 Vue版本: "^2.6.10" - abhilash-ram
也许我误解了你的意思,但这是所提问的期望结果。 - D-Marc

5
我的答案怎么样,有更少的属性,更容易理解吗?

new Vue({
  el: '#app',
  data: {
    users: [{
      "id": "1",
      "name": "Shad Jast",
      "email": "pfeffer.matt@yahoo.com",
      'checked': false
    }, {
      "id": "2",
      "name": "Duane Metz",
      "email": "mohammad.ferry@yahoo.com",
      'checked': false
    }, {
      "id": "3",
      "name": "Myah Kris",
      "email": "evolkman@hotmail.com",
      'checked': false
    }, {
      "id": "4",
      "name": "Dr. Kamron Wunsch",
      "email": "lenora95@leannon.com",
      'checked': false
    }, ],

  },
  computed: {
    selectAll: function() {
      return this.users.every(function(user){
        return user.checked;
      });
    }
  },
  methods: {
    toggleSelect: function() {
      var select = this.selectAll;
      this.users.forEach(function(user) {

        user.checked = !select;

      });
      this.selectAll = !select;
    },

  }
});
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
  <h4>User</h4>
  <div>
    <table>
      <tr>
        <th>Name</th>
        <th>Select
          <input type="checkbox" @click="toggleSelect" :checked="selectAll">
        </th>
      </tr>
      <tr v-for="user in users">
        <td>{{ user.name }}</td>
        <td>
          <input type="checkbox" v-model="user.checked">
        </td>
      </tr>
    </table>
  </div>

</div>


1
我猜这取决于每个数据项是否具有'checked': false - haakym
这个语句 this.selectAll = !select; 是不必要的,因为 this.selectAll 总是依赖于所有用户的选中属性是否被选中。 - LeoYuan 袁力皓

4

感谢大家分享解决方案,这对我的学习有很大帮助。gitter上的开发者帮我添加了一个“默认”复选框,它将选择一个子集,该子集的属性名为“default”,并设置为true。

代码如下:

// based on https://jsfiddle.net/okv0rgrk/3747/

new Vue({
    el: '#app',
    data: {
        selected: [],
        defaultSelects: [],
        selectsArray: [ 

            {id: 'automotive', name: 'Automotive', class: 'industry', default: false},

            {id: 'beauty', name: 'Beauty', class: 'industry', default: true},

            {id: 'branding', name: 'Branding', class: 'industry', default: true},

            {id: 'btob', name: 'B to B', class: 'industry', default: false}
        ],
        selected: [],
    },
    computed: {
      defaultChecked: {
        get () {
          let defaults = this.selectsArray.filter(item => item.default).map(item => item.id)
          const hasAllItems = (baseArr, haystack) => haystack.every(item => baseArr.includes(item))
          const hasSameItems = (baseArr, haystack) => hasAllItems(baseArr, haystack) && hasAllItems(haystack, baseArr)
          return hasSameItems(this.selected, defaults)
        },
        set (value) {
          this.selected = []

          if (value) {
            this.selectsArray.forEach((select) => {
              if (select.default) {
                this.selected.push(select.id)
              }
            });
          }
        }
      }, // END defaultChecked
      selectAll: {
        get () {
          return this.selected.length === this.selectsArray.length
        },
        set (value) {
          this.selected = []

          if (value) {
            this.selectsArray.forEach((select) => {
              this.selected.push(select.id)
            })
          }
        }
      }, // END selectAll
    }
})
<script src="https://cdn.jsdelivr.net/vue/latest/vue.js"></script>

<div id="app">
          
<div id="default-settings">

<label class="pref-button"><input type="checkbox" v-model="defaultChecked"><span>Default</span></label>

<label class="pref-button"><input type="checkbox" v-model="selectAll"><span>Select All</span></label>

</div>    
          
<label :for="select.id" v-for="select in selectsArray" v-bind:key="select.id"><input :value="select.id" v-model="selected" :id="select.id" :sector="select.id" :class="select.class" :default="select.default" type="checkbox">{{ select.name }}</label>

<span>Selected Ids: {{ selected }}</span>
  
</div>


3

您所需要做的就是添加用户,使用他们的ID作为复选框中引用其值的方式,并将其添加到您的已选数组中。

selectAll: function() {
    this.selected = [];
    for (user in this.users) {
        this.selected.push(this.users[user].id);
    }
}

运行 JSFiddle


1
谢谢您的回复。这对于选择所有值来说非常好,但是如何取消选择呢? - haakym
我猜我可以检查选中全部是否为真或假,如果为假,则从选定中删除所有内容? 我将在您的 fiddle 中尝试。 - haakym
哇!搞定了,我会稍微修改你的答案,希望没关系?已经用解决方案更新了你的fiddle。感谢你的帮助,伙计。 - haakym
好的回答,nhydock。 - Nelson Katale

2
这里是最简单的解决方案,只需要使用 v-modelcomputed。不需要额外的 数组、@click、:checkedHTML
<div id="app">
   <input type="checkbox" v-model="allSelected"> Select All

   <ul>
      <li v-for="user in users">
         <input type="checkbox" v-model="user.selected"> {{ user.name }}
      </li>
   </ul>

   <button @click="getSelectedUsers">Get Selected Users</button>
</div>

JS

new Vue({
  el: "#app",
  data: {
    users: [
      {
        id: 1,
        name: "Alda Myrrhine",
        selected: false,
      },
      {
        id: 2,
        name: "Amrita Rabi",
        selected: false,
      },
      {
        id: 3,
        name: "Ruza Alannah",
        selected: false,
      },
    ]
  },
  computed: {
    allSelected: {
      set (selected) {
        this.users.forEach(function (user) {
          user.selected = selected;
        });
      },
      get () {
        return this.users.every(function (user) {
          return user.selected;
        });
      }
    }
  },
  methods: {
    getSelectedUsers () {
      let users = this.users.filter((user) => {
        return user.selected;
      });
      
      console.log(users);
    }
  }
})

请注意,您需要从一开始就存在属性user.selected(例如,如果您从API或其他地方加载数据)。
工作示例:https://jsfiddle.net/y8gujf2p/

1
我有一个更简单的解决方案,如下所示,并且它具备你想要的所有功能。真实数据应该放入一个映射中,将名称索引为复选框的标签,以便未来轻松访问。
<template>
  <div align="left">
    <div>
      <input type="checkbox" id="all" :checked="allNamesSelected" @click="selectAll()">
      <label for="all">All</label>
    </div>
    <div v-for="(name) in names" :key="name">
      <input type="checkbox" :id="name" :value="name" :check="isChecked(name)" v-model="selectedNames">
      <label :for="name">{{name}}</label>
    </div>
  </div>
</template>

<script>
export default {
    data() {
        return {
            names: ['Automotive', 'Beauty', 'Branding', 'B to B'],
            selectedNames: [],
        }; 
    },
    computed: {
        allNamesSelected() {
            return this.names.length == this.selectedNames.length;
        },
    },
    methods: {
        selectAll() {
            if (this.allNamesSelected) {
                this.selectedNames = [];
            } else {
                this.selectedNames = this.names.slice();
            }
        },
        isChecked(name) {
            return this.selectedNames.includes(name);
        }
    }
}
</script>

1

我认为这可能会更容易一些。

selectAll: function (isSelected) {
  if (!isSelected) {
    this.ids = []
    return false
  }
  if (isSelected) {
    this.rows.map(item => this.ids.push(item.id))
  }
}

0
通常情况下,在表格下方不需要显示所选ID。在这种情况下,上述代码可以简化为:

HTML

<div id="app">
    <h4>Users</h4>
    <div>
        <table>
            <tr>
                <th>Name</th>
                <th>Select <input type="checkbox" v-model="selectAll"></th>
            </tr>
            <tr v-for="user in users">
                <td>{{ user.name }}</td>
                <td><input type="checkbox" :value="user.id" :checked="selectAll"></td>
            </tr>
        </table>
    </div>
</div>

VueJs

new Vue({
    el: '#app',
    data: {
        users: [ 
            { "id": "1", "name": "Shad Jast", "email": "pfeffer.matt@yahoo.com"}, 
            { "id": "2", "name": "Duane Metz", "email": "mohammad.ferry@yahoo.com"}, 
            { "id": "3", "name": "Myah Kris", "email": "evolkman@hotmail.com"}, 
            { "id": "4", "name": "Dr. Kamron Wunsch", "email": "lenora95@leannon.com"}, 
            { "id": "5", "name": "Brendon Rogahn", "email": "verlie.buckridge@yahoo.com"}
        ],
        selectAll: false
    }
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接