vue+elememt-ui el-select组件封装

这篇具有很好参考价值的文章主要介绍了vue+elememt-ui el-select组件封装。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最终效果图:
vue封装select组件,elementui,vue,前端框架
用的是vue2写法,喜欢用vue3的同学可以自行修改下。

需求要求

  1. 实现el-select功能复用;
  2. 支持单选或者多选功能;
  3. 支持全拼或者简拼搜索功能;

直接上代码:

pinyin.js文件

import PinYin from "pinyin";
/**
 *
 * @param { String } q - 翻译的全拼key值
 * @param { String } j - 翻译的简拼key值
 * @return { Object }
 */
export default function(str, q, j) {
  q = q || "q";
  j = j || "j";
  let obj = {
    [q]: "",
    [j]: ""
  };
  if (str) {
    obj[q] =
      PinYin(str, {
        style: PinYin.STYLE_NORMAL
      }).join("") || "";
    obj[j] =
      PinYin(str, {
        style: PinYin.STYLE_FIRST_LETTER
      }).join("") || "";
  }
  return obj;
}
// 注册全局汉字转拼音方法
import pinyin from "@/utils/pinyin";
Vue.prototype.$pinyin = pinyin;
父组件
<select-multiple
  :id.sync="form.shop"
  :list="initData.shops"
  name="适用门店"
  placeholder="请选择适用门店"
  type="Array"
></select-multiple>
子组件
<template>
  <el-select
    v-model="data_id"
    :placeholder="placeholder || `请选择${name}`"
    @change="changeData"
    clearable
    filterable
    collapse-tags
    :no-data-text="`未搜索到${name}`"
    loading-text="搜索中"
    :filter-method="remoteMethod"
    :loading="loading"
    :multiple="multiple"
    @visible-change="visibleChange"
    :default-first-option="true"
    :disabled="disabled"
  >
    <div style="text-align: center; margin-bottom: 10px" v-show="multiple && isShowCheck">
      <el-checkbox v-model="checked" @change="dataSelectAll">全选</el-checkbox>
    </div>
    <el-option
      v-for="item in options"
      :key="item[value] + Math.random()"
      :label="item[label]"
      :value="item[value]"
    >
    </el-option>
  </el-select>
</template>

<script>
export default {
  props: {
    // 搜索placeholder
    placeholder: {
      type: String,
      default: ""
    },
    // 搜索名称
    name: {
      type: String,
      default: "门店"
    },
    // option选项的value键名
    value: {
      type: String,
      default: "id"
    },
    // option选项的label键名
    label: {
      type: String,
      default: "name"
    },
    // 传进来的选中数据
    id: [String, Number, Array],
    // 筛选项数据
    list: Array,
    // 多选数据分隔符
    separator: {
      type: String,
      default: "_"
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: true
    },
    // 传值类型 string、array
    type: {
      type: String,
      default: "String"
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 全拼的键名,默认为q
    q: {
      type: String,
      default: "q"
    },
    // 简拼的键名,默认为j
    j: {
      type: String,
      default: "j"
    }
  },
  data() {
    return {
      // 选中数据ID
      data_id: [],
      // 搜索数据加载状态
      loading: false,
      // 简拼搜索添加防抖
      methodTimer: null,
      // 获取到全部的数据
      allOptions: [],
      // 展示的数据
      options: [],
      // 全选、反选
      checked: false,
      // 是否显示全选按钮
      isShowCheck: true
    };
  },
  methods: {
    // 监听选择值变化
    changeData(val) {
      if (this.multiple) {
        if (val.length === this.allOptions.length) {
          this.checked = true;
        } else {
          this.checked = false;
        }
        if (this.type === "String") {
          this.$emit("update:id", val.join(this.separator));
          this.$emit("change", val.join(this.separator));
        } else if (this.type === "Array") {
          this.$emit("update:id", val);
          this.$emit("change", val);
        }
      } else {
        this.$emit("update:id", val);
        this.$emit("change", val);
      }
    },
    // 搜索输入字符监控
    remoteMethod(query) {
      if (this.methodTimer) {
        clearTimeout(this.methodTimer);
      }
      if (query !== "") {
        this.isShowCheck = false;
        this.loading = true;
        if (this.methodTimer) {
          clearTimeout(this.methodTimer);
        }
        query = query.toLowerCase();
        this.methodTimer = setTimeout(() => {
          this.options = this.allOptions.filter(i => {
            return (
              (i[this.q] && i[this.q].indexOf(query) !== -1) ||
              (i[this.j] && i[this.j].indexOf(query) !== -1) ||
              (i[this.label] && i[this.label].indexOf(query) !== -1)
            );
          });
          this.loading = false;
          clearTimeout(this.methodTimer);
        }, 500);
      } else {
        this.loading = false;
        this.isShowCheck = true;
        this.computedOptions();
      }
    },
    // 给可选项赋值全部数据
    computedOptions() {
      this.options = JSON.parse(JSON.stringify(this.allOptions));
    },
    // 下拉框显示隐藏事件
    visibleChange(val) {
      if (val) {
        this.computedOptions();
      }
    },
    // 选择门店全选&&反选
    dataSelectAll() {
      this.data_id = [];
      if (this.checked) {
        this.data_id = this.allOptions.map(item => {
          return item[this.value];
        });
      }
      this.changeData(this.data_id);
    }
  },
  watch: {
    // 监听门店数据变化
    list: {
      handler(val) {
        if (val.length) {
          const options = JSON.parse(JSON.stringify(val));
          this.allOptions = options.map(i => {
            return Object.assign(i, this.$pinyin(i[this.label], this.q, this.j));
          });
          this.computedOptions();
        } else {
          this.allOptions = [];
          this.options = [];
        }
      },
      deep: true,
      immediate: true
    },
    id: {
      handler(val) {
        if (this.multiple) {
          let isTrue = false;
          if (this.type === "String") {
            isTrue = this.data_id.join(this.separator) != val;
          } else {
            isTrue = this.data_id.join(this.separator) != val.join(this.separator);
          }
          if (isTrue) {
            if (!val) {
              this.checked = false;
              this.data_id = [];
            } else {
              if (this.type === "String") {
                this.data_id = val.split(this.separator);
              } else {
                this.data_id = val;
              }
              this.computedOptions();
            }
          }
        } else {
          this.data_id = val;
          this.computedOptions();
        }
      },
      deep: true,
      immediate: true
    }
  }
};
</script>

<style lang="scss" scoped>
::v-deep.el-select {
  width: 100%;
}
::v-deep.el-select .el-select__tags {
  .el-tag {
    max-width: 100px;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}
</style>

希望对大家有帮助哟!文章来源地址https://www.toymoban.com/news/detail-523895.html

到了这里,关于vue+elememt-ui el-select组件封装的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包