element-ui 之 后台系统常用组件封装

目录

1.搜索框组件

 封装

使用

2.筛选组件

封装

使用


1.搜索框组件

 封装

<template>
  <div class="search-filter-wrapper">
    <div @keyup.enter="searchConfirm" class="display-inline-block input-search-wrapper">
      <el-input
        class="search-input"
        :style="`width:${searchWidth}`"
        :placeholder="placeholder"
        v-model="searchModel"
        :maxlength="40"
        clearable
      >
        <i slot="prefix" class="el-input__icon el-icon-search fontSize15" />
      </el-input>
      <el-button class="search-btn primary-btn" type="primary" @click="searchConfirm">
        <span class="el-icon-search fontSize15"></span>
        <span>{
   
   { label }}</span>
      </el-button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'search-filter',
  props: {
    // 宽度
    searchWidth: {
      type: String,
      default: '500px'
    },
    placeholder: {
      type: String,
      default: '请输入你要搜索的内容'
    },
    label: {
      type: String,
      default: '搜索'
    }
  },
  data() {
    return {
      //input输入框的值
      searchModel: '',
      // 用来做简单防抖函数所用
      timer: null
    };
  },
  methods: {
    // 回车或者点击搜索触发
    searchConfirm() {
      // 简单弄个防抖函数
      if (this.timer) clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.searchModel = this.searchModel.replace(/(^\s+)|(\s+$)/g, '');
        this.$emit('change', this.searchModel);
      }, 500);
    }
  }
};
</script>

<style lang="scss" scoped>
.search-filter-wrapper {
  display: inline-block;
  .display-inline-block {
    display: inline-block;
    .search-input {
      height: 36px;
      vertical-align: middle;
    }
  }
  .search-btn {
    position: relative;
    vertical-align: middle;
  }
}
</style>

使用

<template>
    <search-filter
         ref="searchFilter"
         placeholder="客户姓名、编号"
         @change="searchValueChange"
    />
</template>

import searchFilter from '@/components/common/searchFilter';

export default{
    data(){
        return {
            // 搜索的值
            serachStr:''
        }
    }
    components: {searchFilter},
    methods:{
        // 获取搜索变化值
        searchValueChange(value){
            this.serachStr = value
            // 发起请求获取数据
            this.getData();
        }
    }
}

2.筛选组件

用数据来驱动,用数组来快速搭建筛选组件,让你摆脱烦恼~

暂时只封装了   输入框、文本域、下拉框(单选|多选)、带搜索的输入框、单选、级联选择

后续慢慢完善

封装

<template>
  <div class="tableFilter-layout">
    <!-- 可能有众多条件,弄成个数据 -->
    <template v-for="(item, index) in editMsgObj">
      <span class="list-filter-item" :key="index">
        <!-- 各个筛选框前的文字描述 -->
        <span class="list-filter-item-key" v-if="item.text">{
   
   { item.text || '' }}:</span>
        <!-- 筛选框 用来判断是哪类筛选框 -->
        <span class="list-filter-item-input-wrapper">
          <!-- 输入框 || 文本域 -->
          <template v-if="item.type === 'input' || item.type === 'textarea'">
            <el-input
              v-model="item.model"
              :type="item.type === 'textarea' ? 'textarea' : 'text'"
              :name="item.elemName"
              :maxlength="item.maxlength || 50"
              :placeholder="item.placeholder || ''"
              :rows="4"
              :disabled="!!item.disabled"
              @change="changeItemValue(item)"
            />
          </template>
          <!-- 下拉框单选 || 下拉框多选-->
          <template v-else-if="item.type === 'select' || item.type === 'multipleSelect'">
            <el-select
              v-model="item.model"
              popper-class="default-select-dropdown"
              :name="item.elemName"
              :disabled="!!item.disabled"
              :placeholder="item.placeholder || '- -'"
              :clearable="!item.cleardisable || item.type === 'multipleSelect'"
              :multiple="item.type === 'multipleSelect'"
              :filterable="!!item.filterable"
              :collapse-tags="item.type === 'multipleSelect'"
              @change="changeItemValue(item)"
            >
              <template v-for="type in item.values">
                <el-option
                  :label="type.itemName"
                  :value="type.itemKey"
                  :key="type.itemKey"
                ></el-option>
              </template>
            </el-select>
          </template>
          <!-- 带搜索的输入框 -->
          <template v-else-if="item.type === 'search'">
            <span @keyup.enter="searchFunc" class="display-inline-block input-search-wrapper">
              <el-input
                class="search-input"
                :placeholder="item.placeholder"
                v-model="item.model"
                :maxlength="item.maxlength || 50"
                :clearable="!item.cleardisable"
              >
                <i slot="prefix" class="el-input__icon el-icon-search fontSize15"></i>
              </el-input>
              <el-button class="search-btn primary-btn" type="primary" @click="searchFunc">
                <span class="el-icon-search fontSize15"></span>
                <span>搜索</span>
              </el-button>
            </span>
          </template>
          <!-- 单选-->
          <template v-else-if="item.type === 'radio'">
            <el-radio-group v-model="item.model" :name="item.name" @change="changeItemValue(item)">
              <template v-for="(type, idx) in item.values">
                <el-radio :label="type.itemKey" :key="idx">
                  {
   
   { type.itemName }}
                </el-radio>
              </template>
            </el-radio-group>
          </template>
          <!-- 级联选择 -->
          <template v-if="item.type === 'cascader'">
            <el-cascader
              popper-class="default-select-dropdown"
              v-model="item.model"
              :options="item.values"
              :clearable="true"
              :collapse-tags="true"
              :show-all-levels="false"
              :props="{
                value: 'itemKey',
                label: 'itemName',
                children: 'children',
                multiple: !item.checkStrictly,
                checkStrictly: !!item.checkStrictly
              }"
              placeholder="请选择内容"
              @change="changeItemValue(item)"
            ></el-cascader>
          </template>
        </span>
      </span>
    </template>
    <!-- 如果需要有输入框 -->
    <el-button
      v-if="searchBtn"
      class="search-btn primary-btn"
      type="primary"
      @click="searchBtnFunc"
    >
      <span class="el-icon-search fontSize15"></span>
      <span>搜索</span>
    </el-button>
  </div>
</template>
<script>
export default {
  name: 'tableFilter',
  components: {},
  filters: {},
  props: {
    // 编辑内容
    editObj: {
      type: [Object, Array],
      default: function () {
        return {};
      }
    },
    // 是否需要搜索确认框
    searchBtn: Boolean
  },
  data() {
    return {
      // 是否是数组   数组返回整个对象,对象返回key-value
      ifArray: false,
      // 编辑内容
      editMsgObj: {},
      // 搜索
      searchModel: ''
    };
  },
  computed: {},
  watch: {
    // 实时更新
    editObj: {
      handler(to, from) {
        this.editMsgObj = this.dealAdvanceList(this.deepCopy(this.editObj));
      },
      deep: true
    }
  },
  mounted() {
    this.editMsgObj = this.dealAdvanceList(this.deepCopy(this.editObj));
  },
  methods: {
    /**
     * 监听方法
     */
    // 初始化   用来清空值 比如 this.$refs.listFitler.initFunc() 这样调用;
    initFunc() {
      this.editMsgObj = this.dealAdvanceList(this.deepCopy(this.editObj));
    },
    // 处理值
    dealAdvanceList(data) {
      data = data || {};
      let resData = {};
      // 判断是否是数组还是对象
      if (data instanceof Array) {
        this.ifArray = true;
        data.forEach((item, index) => {
          resData[item.name] = item;
        });
      } else {
        this.ifArray = false;
        resData = data;
      }
      return resData;
    },
    // 选项触发
    changeItemValue() {
      if (this.searchBtn) return;
      this.changeVal(this.editMsgObj);
    },
    // 改变editObj某一项的值  例如this.$refs.editItem.changeEditModelVal('isRepay', 'hidden', true);
    changeEditModelVal(key, attr, val) {
      if (!this.editMsgObj[key]) {
        return;
      }
      this.editMsgObj[key][attr] = val;
    },
    // 值改变,数据拼接
    changeVal(obj) {
      let newObj = {};
      let newArr = [];
      for (let key in obj) {
        if (Array.isArray(obj[key].model) && obj[key].model.length > 0) {
          console.log(88);
          // 返回的数据是数组类型 例如 多选 级联选择器
          newObj[key] = obj[key].model;
          let idx = newArr.length;
          newArr.push(this.deepCopy(obj[key]));
          obj[key].model.forEach((itemValue, itemIdx) => {
            newArr[idx].values.push({
              itemKey: itemValue
            });
          });
          delete newArr[idx].model;
        } else if (obj[key].model || obj[key].model === 0) {
          // 返回的数据是字符串类型 例如单选 文本输入框
          console.log(666);
          newObj[key] = obj[key].model;
          let idx = newArr.length;
          newArr.push(this.deepCopy(obj[key]));
          newArr[idx].values = [{ itemKey: obj[key].model }];
          delete newArr[idx].model;
        } else if (obj[key].type === 'search' && obj[key].model) {
          newObj[key] = obj[key].model;
          let idx = newArr.length;
          newArr.push(this.util.deepCopy(obj[key]));
          newArr[idx].value = obj[key].model;
        }
      }
      let result = this.ifArray ? newArr : newObj;
      this.$emit('editMsgObjChange', result);
    },
    // 搜索
    searchFunc() {
      this.changeVal(this.editMsgObj);
    },
    // 搜索按钮促发
    searchBtnFunc() {
      this.changeVal(this.editMsgObj);
    },
    // 深拷贝
    deepCopy(o) {
      // 数组
      if (o instanceof Array) {
        return o.map((item) => {
          return this.deepCopy(item);
        });
      } else if (o instanceof Function) {
        return o;
      } else if (o instanceof Object) {
        let temp = {};
        Object.keys(o).map((item) => {
          temp[item] = this.deepCopy(o[item]);
        });
        return temp;
      } else {
        return o;
      }
    }
  }
};
</script>
<style lang="scss" scoped>
.tableFilter-layout {
  .list-filter-item {
    display: inline-block;
    margin-bottom: 10px;
    margin-right: 10px;
    .el-input {
      width: 185px;
    }
  }
}
</style>

使用

<!-- //?模块说明 =>  模块 -->
<template>
  <div class="About-layout">
    <!-- 
      editObj : 筛选条件数组
      editMsgObjChange: 选项触发后
     -->
    <table-filter
      ref="tableFitler"
      :editObj="tableFilterData"
      @editMsgObjChange="changeFilterObj"
      :searchBtn="true"
    ></table-filter>
  </div>
</template>
<script>
import tableFilter from './components/tableFilter';
export default {
  name: 'About',
  components: { searchFilter, tableFilter },
  filters: {},
  props: {},
  data() {
    return {
      searchStr: '',
      tableFilterData: {
        // 活动类型
        activeType: {
          name: 'activeType',
          // 规定类型  =>  下拉框多选
          type: 'multipleSelect',
          // 显示筛选框前面的文字
          text: '流转类型',
          // 选中的数据,因为是多选,所以是数组
          model: [],
          elemName: 'list-activeType',
          // 供选择的数据,可以通过接口获得,也可以写死
          values: [
            { itemKey: 0, itemName: '吃饭' },
            { itemKey: 1, itemName: '睡觉' }
          ],
          // 默认提示文字
          placeholder: '全部',
          // 是否可删除
          clearable: true
        },
        // 是否成交
        isHasBuy: {
          name: 'isHasBuy',
          // 规定类型  =>  下拉框单选
          type: 'select',
          text: '是否成交',
          // 选中的数据,因为是单选,所以是字符串
          model: '',
          elemName: 'list-isHasBuy',
          // 供选择的数据,可以通过接口获得,也可以写死
          values: [
            { itemKey: 0, itemName: '成交' },
            { itemKey: 1, itemName: '未成交' }
          ],
          placeholder: '全部',
          clearable: true
        },
        // 搜索框
        fuzzySearch: {
          name: 'fuzzySearch',
          // 规定类型  =>  有搜索的输入框,一般一个页面只使用一个
          type: 'search',
          // 输入的数据,
          text: '',
          placeholder: '请输入内容',
          model: '',
          elemName: 'list-fuzzySearch'
        },
        // 性别
        sex: {
          name: 'sex',
          // 规定类型  =>  单选
          type: 'radio',
          text: '性别',
          // 选择的数据,
          model: '',
          maxlength: 20,
          elemName: 'list-sex',
          values: [
            { itemKey: 0, itemName: '男' },
            { itemKey: 1, itemName: '女' }
          ]
        },
        // 地区
        areas: {
          name: 'areas',
          type: 'cascader',
          text: '地区',
          model: [],
          value: '',
          disabled: false,
          values: [
            {
              itemKey: 110000,
              itemName: '北京',
              children: [
                {
                  itemKey: 110100,
                  itemName: '北京市'
                }
              ]
            },
            {
              itemKey: 410000,
              itemName: '河南省',
              children: [
                {
                  itemKey: 410100,
                  itemName: '郑州市'
                },
                {
                  itemKey: 410200,
                  itemName: '开封市'
                }
              ]
            }
          ],
          elemName: 'list-areas',
          span: 8,
          cleardisable: true,
          filterable: true,
          validateObj: {
            errorTip: '',
            ifRequiredFill: false
          }
        }
      }
    };
  },
  computed: {},
  watch: {},
  mounted() {
    let obj = [];
    // console.log({}.toString.call(obj));
    // console.log([].toString.call(obj));
  },
  methods: {
    /**
     * 监听方法
     */
    // 筛选条件变动
    changeFilterObj(obj) {
      console.log(obj);
    }
    /**
     * 请求数据
     */
  }
};
</script>
<style lang="scss" scoped>
//.About-layout{}
</style>

后续会慢慢更新其他的筛选,比如常用的还有时间选择框、敬请期待!

猜你喜欢

转载自blog.csdn.net/a15297701931/article/details/124491969
今日推荐