vue实现自定义checkbox组件

效果展示

在这里插入图片描述

父组件中使用

<checkbox-group v-model="checkList">
        <checkbox
          v-for="(item,index) in data"
          v-bind:key="index"
          :label="item.name"
          :value="item.id"
        ></checkbox>
</checkbox-group>

Checkbox.vue

<template>
  <div class="checkbox-wrap" @click="handleClick">
    <div class="left" :class="isChecked?'box-click':''" ref="box">
      <transition name="fade">
        <div class="hook" v-show="isChecked"></div>
      </transition>
    </div>
    <div class="right">{{label}}</div>
  </div>
</template>
<script lang='ts'>
import { Component, Vue, Watch, Prop } from "vue-property-decorator";
@Component({
  components: {}
})
export default class extends Vue {
  private isChecked: boolean = false;
  @Prop()
  private label!: string;
  @Prop()
  private value!: string;
  private handleClick() {
  	this.isChecked = !this.isChecked;
    if (this.isChecked) {
      this.$parent.$emit("pushItem", this.value);
    } else {
      this.$parent.$emit("removeItem", this.value);
    }
    this.$emit("input", this.isChecked);
  }
}
</script>
<style scoped lang="scss">
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
.checkbox-wrap {
  height: 24px;
  display: inline-block;
  vertical-align: center;
  margin-bottom: 5px;
  .left {
    height: 24px;
    width: 24px;
    border-radius: 7px;
    background-color: #ffffff;
    display: inline-block;
    border: 1.2px solid #cccccc;
    box-sizing: border-box;
  }
  .right {
    margin-left: 5px; 
    padding-right: 10px;
    display: inline;
    vertical-align: top; // 内联元素默认的vertical-align为baseline。对象的内容与基线对齐。如果我们在right插入文字。则为出现left right不水平对齐的情况
    line-height: 24px;
    color: #66757f;  // 在mounted
    font-size: 15px;
  }
  .box-click {
    background-color: #1da1f2;
    border: 0.5px solid #cccccc;
  }
  .hook {
    margin-left: 8px;
    margin-top: 2px;
    width: 5px;
    height: 12px;
    border-right: 1.3px solid #ffffff;
    border-bottom: 1.3px solid #ffffff;
    transform: rotate(40deg);
  }
}
.checkbox-wrap:hover {
  cursor: pointer;
}
</style>

CheckboxGroup.vue

<template>
  <div class="checkbox-group-wrap">
    <slot></slot>
  </div>
</template>
<script lang='ts'>
import { Component, Vue, Watch, Prop } from "vue-property-decorator";
@Component({
  components: {}
})
export default class extends Vue {
  private checkBoxGroup: string[] = [];
  private pushItem(value) {
    this.checkBoxGroup.push(value);
    this.$emit("input", this.checkBoxGroup);
  }
  private removeItem(value) {
    const index = this.checkBoxGroup.indexOf(value);
    this.checkBoxGroup.splice(index, 1);
    this.$emit("input", this.checkBoxGroup);
  }
  private mounted() {
    this.$on("pushItem", this.pushItem);
    this.$on("removeItem", this.removeItem);
  }
}
</script>
<style scoped lang="scss">
</style>

这里script部分是用ts写的,你可以改成js的语法。template和style部分不用改。注意这里子组件checkbox作为slot触发父组件checkboxGroup事件pushItem的用法。slot不能绑定事件

发布了51 篇原创文章 · 获赞 18 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_42565137/article/details/99677754
今日推荐