Bootstrap

vue自定义封装一个多选选择器组件

组件封装

封装的目的就是为了能够更加便捷、快速的进行业务功能的开发。组件(component)是vue的最强大功能之一,组件可以实现一些类似功能的复用及与其它业务逻辑的解耦。在开发中,我们难免会写很多类似的、重复的代码,有时候两个业务模块有相似的功能,采用复制粘贴已经很省事,但如果涉及的字段或有一些小差别,你也会觉得很烦,毕竟你要从头到尾瞅着去改动。这时候如果把那些相同的功能,抽象出来抽离成组件,通过组件引用方式就会显得格外省事了



效果图

  • 先上效果图
    请添加图片描述

代码

1.子组件代码

<template>
  <div :class="!plain ? 'box' : 'box_plain'">
    <div
      class="box_item"
      v-for="(item, index) in options"
      :key="index"
      @click="boxClick(item)"
      :class="
        valueKey
          ? boxValue.indexOf(item[valueKey]) === -1
            ? ''
            : 'is-active'
          : boxValue.indexOf(item) === -1
          ? ''
          : 'is-active'
      "
    >
      {{ item[labelKey] }}
    </div>
  </div>
</template>

<script>
export default {
  props: {
    //多选数据
    options: {
      type: Array,
      default: () => []
    },
    // 是否是边框模式
    plain: {
      type: Boolean,
      default: false
    },
    // label绑定的值,默认为label,可以自定义
    labelKey: {
      type: String,
      default: "label"
    },
    // 值绑定的值,默认为"",可以自定义
    valueKey: {
      type: String,
      default: ""
    },
    // 选中的值,默认为[],可以自定义
    value: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      boxValue: this.value
    };
  },
  created() {},
  computed: {},
  methods: {
    // 多选点击事件
    boxClick(item) {
      if (!this.valueKey) {
        if (this.boxValue.indexOf(item) === -1) {
          this.boxValue.push(item);
        } else {
          this.boxValue.splice(this.boxValue.indexOf(item), 1);
        }
      } else {
        if (this.boxValue.indexOf(item[this.valueKey]) === -1) {
          this.boxValue.push(item[this.valueKey]);
        } else {
          this.boxValue.splice(this.boxValue.indexOf(item[this.valueKey]), 1);
        }
      }
    }
  },
  watch: {
    //原生v-model绑定的值
    boxValue(val) {
      this.$emit("input", val);
    },
    //原生v-model绑定的值
    value(val) {
      this.boxValue = val;
    }
  }
};
</script>

<style lang="scss" scoped>
.box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  .box_item {
    cursor: pointer;
    box-sizing: border-box;
    width: 100px;
    height: 40px;
    background: #5271c4;
    margin: 2px 10px 2px 0;
    color: #fff;
    border-radius: 5px;
    text-align: center;
    line-height: 40px;
    overflow: hidden;
  }
  .box_item:hover {
    opacity: 0.8;
  }
  .is-active {
    position: relative;
    border: 1px solid #5271c4;
  }
  .is-active::after {
    content: "\2714";
    color: #5271c4;
    line-height: 20px;
    padding: 3px 0 0 5px;
    box-sizing: border-box;
    position: absolute;
    overflow: hidden;
    bottom: 0;
    right: 0;
    width: 20px;
    height: 20px;
    background: linear-gradient(
      -45deg,
      #fff,
      #fff 50%,
      transparent 50%,
      transparent 100%
    );
  }
}
.box_plain {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  .box_item {
    cursor: pointer;
    box-sizing: border-box;
    width: 100px;
    height: 40px;
    border: 1px solid $leftColor;
    margin: 2px 10px 2px 0;
    font-weight: 700;
    color: #5271c4;
    border-radius: 5px;
    text-align: center;
    line-height: 40px;
    // box-shadow: 5px 5px 15px $leftColor;
    overflow: hidden;
  }
  .box_item:hover {
    opacity: 0.8;
  }
  .is-active {
    position: relative;
  }
  .is-active::after {
    content: "\2714";
    color: #fff;
    font-weight: normal;
    line-height: 20px;
    padding: 3px 0 0 5px;
    box-sizing: border-box;
    position: absolute;
    overflow: hidden;
    bottom: 0;
    right: 0;
    width: 20px;
    height: 20px;
    background: linear-gradient(
      -45deg,
      #5271c4,
      #5271c4 50%,
      transparent 50%,
      transparent 100%
    );
  }
}
</style>

2.父组件中使用

//设置:value-key、label-key可指定绑定数据,和显示内容\不设置value-key默认绑定全部属性;plain属性为边框模式
//填充模式:
 <boxselect v-model="value3" :value-key="'value'" :label-key="'label'" :options="options" />
//边框模式:
 <boxselect v-model="value4" :options="options" plain />

//数据
data() {
    return {
		options: [
        {
          value: "选项1",
          label: "黄金糕"
        },
        {
          value: "选项2",
          label: "双皮奶"
        },
        {
          value: "选项3",
          label: "蚵仔煎"
        },
        {
          value: "选项4",
          label: "龙须面"
        },
        {
          value: "选项5",
          label: "北京烤鸭"
        }
      		],
      	value3: [],
      	value4: [],
      	}
     },
//注册组件
 	components: {
    	boxselect: () => import("./components/boxselect.vue")
  	},

有疑惑可以私聊我哦🤞🤞🤞

;