从零实现Vue的组件库(十五)- Checkbox-Group 实现

栏目: 编程语言 · 发布时间: 7年前

内容简介:代码实例地址:CheckboxGroup 实例代码地址:
CheckboxGroup 组件与 RadioGroup 组件类似,但是也存在不同点,在于 CheckboxGroup 为多选组,并且需要 Checkbox 可以单独使用。

1. 实例

从零实现Vue的组件库(十五)- Checkbox-Group 实现

代码

<!-- 基础用法 -->
<fat-checkbox-group v-model="anotherValue">
    <fat-checkbox value="あらがき ゆい">
        <fat-hover-tip type="right-center">
            <template slot="hover-part">あらがき ゆい</template>
            <template slot="tip-part">
                <img src="/static/img/gakki.jpg" style="width: 100px" alt="示意图">
            </template>
        </fat-hover-tip>
    </fat-checkbox>
    <fat-checkbox value="石原さとみ">
        <fat-hover-tip type="right-center">
            <template slot="hover-part">石原さとみ</template>
            <template slot="tip-part">
                <img
                    src="/static/img/u=4046980169,286278015&fm=26&gp=0.jpg"
                    style="width: 100px"
                    alt="示意图"
                >
            </template>
        </fat-hover-tip>
    </fat-checkbox>
</fat-checkbox-group>
复制代码

实例地址:CheckboxGroup 实例

代码地址: Github UI-Library

2. 原理

Checkbox

首先单独实现 Checkbox 组件,它是由 labelinput 两部分构成,主要区分两个状态, checked 以及 disabled

<template>
  <label
    :class="[
        'checkbox-item',
        { 'is-checked': isChecked },
        { 'is-disabled': isDisabled }
    ]"
    @click.stop="handleClick"
  >
    <span class="checkbox-input">
      <fat-icon name="check"/>
    </span>
    
    <input
      v-if="false"
      type="checkbox"
      v-bind="$attrs"
      :value="model"
      @click.stop
    >
    
    <slot></slot>
  </label>
</template>

<script>
export default {
    props: {
        value: {
            type: [String, Number],
            required: true
        },
        disabled: {
            type: [Boolean],
            default: false
        },
        propValue: {
            type: [String, Number, Boolean]
        }
    },
    model: {
        prop: "propValue",
        event: "select"
    },
    computed: {
        isGroup() {
            return this.$parent.$options._componentTag === "fat-checkbox-group";
        },
        isDisabled() {
            return this.$parent.disabled || this.disabled;
        },
        isChecked() {
            const { isGroup, model } = this;
            if (!isGroup) return model;

            const {
                value,
                $parent: { value: selectItems }
            } = this;

            return selectItems.some(item => item === value);
        },
        model: {
            get() {
                return this.isGroup ? this.$parent.value : this.propValue;
            },
            set(newValue) {
                const { isGroup, isChecked } = this;

                if (isGroup) {
                    isChecked
                    ? this.$parent.deleteItem(newValue)
                    : this.$parent.selectItem(newValue);
                } else {
                    this.$emit("select", newValue);
                }
            }
        }
    },
    methods: {
        handleClick(event) {
            const { isDisabled, isGroup, model, value } = this;
            if (!isDisabled) {
                this.model = isGroup ? value : !model;
            }
        }
    }
};
</script>
复制代码

Radio 一样,由于需要实现 Checkout 可以单独使用的,所以不采用 provide / inject api,而是利用 this.$parent.$options._componentTag 判断,当前组件是否为 Group

同时,依据当前组件是否为 Group 来定义 isDisabledisChecked 等状态的判断条件,例如

isChecked() {
    const { isGroup, model } = this;
    if (!isGroup) return model;
    
    const {
        value,
        $parent: { value: selectItems }
    } = this;
    
    return selectItems.some(item => item === value);
}
复制代码

如果当前为多选组,就会利用 some 来判断当前 Checkout 的 value 是否在其中,然后如果单独使用,则直接返回 model

同样, model 的值也是依据 isGroup 进行区分

model: {
    get() {
        return this.isGroup ? this.$parent.value : this.propValue;
    },
    set(newValue) {
        const { isGroup, isChecked } = this;

        if (isGroup) {
            isChecked ? this.$parent.deleteItem(newValue)
            : this.$parent.selectItem(newValue);
        } else {
            this.$emit("select", newValue);
        }
    }
}
复制代码

CheckboxGroup

则是在 Checkbox 的外部包裹一层 Group 用于,实现组的概念

<template>
    <div class="checkbox-group-wrapper" name="checkbox-group">
        <slot></slot>
    </div>
</template>
<script>
export default {
    name: "checkbox-group",
    props: {
        value: { type: Array, required: true },
        disabled: { type: Boolean }
    },
    model: {
        prop: "value",
        event: "select"
    },
    watch: {
        value(newValue) {
            this.$emit("change", newValue);
        }
    },
    methods: {
        selectItem(item) {
            const { value } = this;
            this.$emit("select", [...value, item]);
        },
        deleteItem(item) {
            const { value: selectItems } = this;
            this.$emit(
                "select",
                selectItems.filter(selectitem => selectitem !== item)
            );
        }
    }
};
</script>
复制代码

Checkbox-Group 内维护了

methods: {
    selectItem(item) {
        const { value } = this;
        this.$emit("select", [...value, item]);
    },
    deleteItem(item) {
        const { value: selectItems } = this;
        this.$emit(
            "select",
            selectItems.filter(selectitem => selectitem !== item)
        );
    }
}
复制代码

用于和 Checkbox 通信,如果当前是多选组的形式,则需要利用 selectItem 以及 deleteItem 来对其进行增减。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Clean Architecture

Clean Architecture

Robert C. Martin / Prentice Hall / 2017-9-20 / USD 34.99

Practical Software Architecture Solutions from the Legendary Robert C. Martin (“Uncle Bob”) By applying universal rules of software architecture, you can dramatically improve developer producti......一起来看看 《Clean Architecture》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

html转js在线工具
html转js在线工具

html转js在线工具