javascript - 如何管理 Vue.js 复选框组件上的复杂状态行为?

标签 javascript vue.js vuejs2 vue-component

在学习 Vue.js 的 1 周中,我试图克服一些挑战。请注意这个example实际上包裹在一个名为 <question> 的父组件中这并不是那么有趣,所以我在这篇文章中简化了我的代码。

  1. 如何将某些项目设置为在加载时默认检查?

编辑 - 我想出了 1。只是不得不做[ "Chicken", "Turkey", "Beef", "Fish", "Pork" ]

  • 如何取消选中某些项目,例如如果我选择素食,则应取消选中肉类选项?
  • 如何在选项旁边添加“排除”和“包含”复选框?
  • enter image description here

    复选框

    <div id="questionnaire">
      <checkbox v-model="form.meats" id="8a"  option="Chicken"></checkbox>
      <checkbox v-model="form.meats" id="8b" option="Turkey"></checkbox>
      <checkbox v-model="form.meats" id="8c" option="Beef"></checkbox>
      <checkbox v-model="form.meats" id="8d" option="Pork"></checkbox>
      <checkbox v-model="form.meats" id="8e" option="Fish"></checkbox>
      <checkbox v-model="form.meats" id="8f" option="Vegetarian Only"></checkbox>
      <checkbox v-model="form.meats" id="8g" option="Vegan Only"></checkbox>
      {{ form.meats }}
    </div>
    

    Vue.component('复选框')

    Vue.component('checkbox', {
      template: `
        <div>
                <input type="checkbox" :id="id" :value="option" v-model="checked" @change="update">
                <label :for="id">
                    {{ option }}
                    <slot></slot>
                </label>
        </div>
        `,
      data() {
        return {
          checkedProxy: false
        }
      },
      computed: {
        checked: {
          get() {
            return this.value
          },
          set(option) {
            this.checkedProxy = option
          }
        }
      },
      methods: {
        update: function(e) {
          this.$emit('input', this.checkedProxy)
        }
      },
      props: {
        value: null,
        option: null,
        id: {
          type: String,
          required: true
        }
      }
    });
    
    new Vue({
      el: "#questionnaire",
      data: {
    
        form: {
    
          meats: [],
    
        }
      }
    })
    

    最佳答案

    我想这些就是你想要的。

    <div id="questionnaire">
      <check-group :chks="chks" v-model="form.meats"></check-group>
      {{ form.meats }}
    </div>
    
    const groups = {
        '1': {
            tag: 'meats',
            exclusiveGroups: [2]
        },
        '2': {
            tag: 'vegan',
            exclusiveGroups: [1]
        }
    }
    
    const chks = {
        'Chicken': {
            groupIds: [1]
        },
        'Turkey': {
            groupIds: [1]
        },
        'Beef': {
            groupIds: [1]
        },
        'Pork': {
            groupIds: [1]
        },
        'Fish': {
            groupIds: [1]
        },
        'Vegetarian Only': {
            groupIds: [2]
        },
        'Vegan Only': {
            groupIds: [2]
        }
    }
    
    Vue.component('checkbox', {
        template: `
        <div>
            <label>
                <input type="checkbox" ref="chk" :value="val" v-model="value" @change="update($event)">
                {{ txt }}
                <slot></slot>
            </label>
            <input type="checkbox" :checked="value.indexOf(val)<0" @change="reverseSelection($event)">
        </div>
        `,
        data () {
            return {
                val: this.optValue || this.optText,
                txt: this.optText || this.optValue
            }
        },
        methods: {
            update (e) {
                this.$emit('input', this.value, e.target.value, e.target.checked)
            },
            reverseSelection () {
                var e = document.createEvent("MouseEvents");
                e.initEvent("click", true, true);
                this.$refs.chk.dispatchEvent(e);
            }
        },
        props: ['value','optValue','optText']
    });
    
    Vue.component('check-group',{
        template: `
            <div>
                <checkbox v-for="item in chks" :opt-value="item.value" :opt-text="item.text" @input="update" v-model="value"></checkbox>
            </div>
        `,
        props: {
            value: {
                required: true,
                type: Array
            },
            chks: {
                required: true,
                type: Array
            }
        },
        methods: {
            update (val,curVal,checked) {
                if(checked){//only checkbox be checked need to judge mutually-exclusive
                    chks[curVal].groupIds.forEach(id=>{//iterate all group of this checkbox
                        groups[id].exclusiveGroups.forEach(eid=>{//iterate all exclusiveGroups of this group
                            for(let i=0;i<val.length;i++){
                                let p = chks[val[i]].groupIds.indexOf(eid)
                                if(p>=0){//if this checkbox's group in exclusiveGroups then remove this item from val Array
                                    val.splice(p,1)
                                    i--
                                }
                            }
                        })
                    })
                }
                this.$emit('input',val)
            },
        }
    })
    
    new Vue({
        el: "#questionnaire",
        data: {
            chks: Object.keys(chks).map(key=>({value: key,groupIds: chks[key]})),
            form: {
                meats: ['Chicken']
            }
        }
    })
    

    如果你想让纯素食和素食不能同时选择, 您可以像这样修改组和 chks 的定义:

    const groups = {
        '1': {
            tag: 'meats',
            exclusiveGroups: [2] //means that when the checkbox of this group be checked,the checkbox whose group-index equals 2 where be unchecked
        },
        '2': {
            tag: 'vegan',
            exclusiveGroups: [1,3]
        },
        '3': {
            tag: 'Vegetarian Only',
            exclusiveGroups: [1,2]
        }
    }
    
    const chks = {
        'Chicken': {
            groupIds: [1]
        },
        'Turkey': {
            groupIds: [1]
        },
        'Beef': {
            groupIds: [1]
        },
        'Pork': {
            groupIds: [1]
        },
        'Fish': {
            groupIds: [1]
        },
        'Vegetarian Only': {
            groupIds: [3]
        },
        'Vegan Only': {
            groupIds: [2]
        }
    }
    

    关于javascript - 如何管理 Vue.js 复选框组件上的复杂状态行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49518946/

    相关文章:

    laravel - v-on :change event for radio input VueJS

    javascript - webpack-cli 错误 : Compiling RuleSet failed

    javascript - 将图像源传递到 Vue.js 中的作用域槽

    javascript - 为什么立方体比正方形快

    javascript - 如何将参数传递给 eventListener 函数并稍后删除该函数?

    javascript - 如何正确配置和使用 WookMark Masonry

    vue.js - VueJs - 在方法之间传递变量

    javascript - 如何使用 JavaScript 抓取 JSON 页面并收集数据

    vue.js - 如何使每个 Vue 构建都包含可在 Vue 应用程序中访问的版本?

    javascript - Vue js 在编译时删除脚本标签