vue + element二次封装更灵活,更易维护的Select组件

前言

select下拉框组件应该是我们在做项目时用的频率比较高的组件之一了,只要涉及到查询,就少不了select下拉框,本文将介绍如何基于vue + element封装一个灵活、易维护的select组件。

1、新建select.vue

下面是select组件的完整代码,里面的内容我将在下面做详解

<template>
  <FormItem :label="label" :prop="dataIndex">
    <Select
      v-model="form[dataIndex]"
      :placeholder="placeholder"
      :size="size"
      :disabled="disabled"
      :clearable="clearable"
      :multiple="multiple"
      :multiple-limit="multipleLimit"
      @change="handleChange"
      style="width: 100%"
    >
      <Option v-for="item in options" :key="item.value" :label="item.name" :value="item.value"></Option>
    </Select>
  </FormItem>
</template>
<script>
import { FormItem, Select, Option } from "element-ui";
import  Store  from "./store/store";

export default {
  name: "selectC",
  components: { FormItem, Select, Option },
  props: {
    form: { required: true, type: Object }, // 表单域(必传)
    dataIndex: { required: true, type: String }, // 绑定值(必传)
    label: { type: String, default: "" }, // 表单项标签名
    disabled: { type: Boolean, default: false }, // 是否禁用
    size: { type: String, default: "medium" }, // 大小,可取值medium / small / mini
    placeholder: { type: String, default: "请选择" }, // 占位文本
    clearable: { type: Boolean, default: false }, // 是否可以清空选项
    multiple: { type: Boolean, default: false }, // 是否多选
    multipleLimit: { type: Number, default: 0 }, // 多选时限制最多选择的数量
    loadType: { type: String }
  },
  data() {
    return {
      store: new Store()
    };
  },
  computed: {
    options() {
      return this.store.SelectStore.getters.options;
    }
  },
  mounted() {
    this.store.SelectStore.dispatch("GET_SELECT_OPTIONS", {
      loadType: this.loadType
    });
  },
  methods: {
    handleChange(e) {
      this.$emit("handleChange", e);
    }
  }
};
</script>

props是组件需要的属性,从父组件传递过来,这里我们需要注意的是loadType这个字段,这个字段表示下拉框的值的加载类型,这个属性会在store中使用到。

另外,我还用到了vuex作为select的状态管理,组件每次被调用,都会实例化一个新的store,这样是防止页面中如果引入多个select组件,会导致下拉框的值不会更新。

关于store中内容,代码如下:

import Vue from 'vue'
import Vuex from 'Vuex'

Vue.use(Vuex)
import {objToArray} from '@/utils'
import {SELECT_TYPES, ORDER_STATUS, ORDER_STATUS_V, REAL_NAME_STATUS, REAL_NAME_STATUS_V} from '@/constants'

class Store {
  constructor() {
    this.SelectStore = this.initStore()
  }

  initStore() {
    return new Vuex.Store({
      state: {
        options: []
      },
      getters: {
        options(state) {
          return state.options
        }
      },
      mutations: {
        getOptions(state, options) {
          state.options = options
        }
      },
      actions: {
        GET_SELECT_OPTIONS({commit}, {loadType}) {
          let options
          switch (loadType) {
            case SELECT_TYPES.ORDER_STATUS:
              options = objToArray(ORDER_STATUS, ORDER_STATUS_V)
              break;
            case SELECT_TYPES.REAL_NAME_STATUS:
              options = objToArray(REAL_NAME_STATUS, REAL_NAME_STATUS_V)
              break;
          }
          commit('getOptions', options)
        }
      }
    })
  }
}

export default Store

我们创建一个Store类,类中的initStore用来创建store,GET_SELECT_OPTIONS方法用于根据传入的loadType字段判断需要加载的下拉框数据,constants文件是存在前端枚举的文件。
在这里插入图片描述
objToArray方法是把枚举转化成数组。

export const objToArray = (nameObj, valueObj) => {
  let arr = []
  Object.keys(nameObj).forEach(key => {
    Object.keys(valueObj).forEach(valKey => {
      if (key === valKey) {
        arr.push({name: nameObj[key], value: valueObj[valKey]})
      }
    })
  })
  return arr
}

2、页面中使用

<template>
  <Form>
    <SelectC :form="form" dataIndex="selectValue" :loadType="loadType" @handleChange="handleChange"/>
  </Form>
</template>

<script>
import SelectC from "@/components/form/Select";
import { Form } from "element-ui";
import { SELECT_TYPES } from "@/constants";
export default {
  name: "edit",
  components: { SelectC, Form },
  data() {
    return {
      form: {
        selectValue: ""
      },
      loadType: SELECT_TYPES.ORDER_STATUS
    };
  },
  methods:{
      handleChange(e){
          console.log(e)
      }
  }
};
</script>

页面效果
在这里插入图片描述

本文结束,感谢观看!觉得有帮助的点个赞!

Logo

前往低代码交流专区

更多推荐