hoc-element

基于 element-ui 库的二次封装,主要包含配置化的 table 表格及 form 表单中的 rules 校验等场景,旨在减少重复的操作,让开发变得更简单。

Usage no npm install needed!

<script type="module">
  import hocElement from 'https://cdn.skypack.dev/hoc-element';
</script>

README

HocElement

npm NPM

🚀 基于 element-ui 库二次封装的一些高阶组件,该组件库主要解决 cms 等管理平台中繁琐的重复代码任务、通过一系列的配置化的思想将列表页的 table 表格及 form 表单中的 rules 校验等场景抽离了出来,旨在减少重复的操作,让开发变得更高效。

Flexibility

  • 通过配置化的方式生成 table 表格, 实现更高的自由度,无需再写大量的诸如 <el-xxx> 的模板
  • 对于表单的 validate rules, 可直接绑定全局的对应规则函数,无需每次复制粘贴
  • 针对图片 upload,只需两个参数 APIv-model,无需写一大堆参数
  • 比较友好的 affix, 支持自定义高度悬停

Environment Support

  • Vue 2.6.0+
  • ElementUI 2.11.1+

Install

npm install hoc-element

Quick Start

import Vue from 'vue'
import HocElement from 'hoc-element'

Vue.use(HocElement)

Components

HocElTable - 可配置的 Table
HocElAffix - 固钉
HocElUploadSingle - 单张图片上传
HocElUploadMultiple - 多张个图片上传

Mixin

RulesForm - Form 表单规则

Using

  • 示例 HocElTable
<template>
  <div class="box-container">
    <div class="content">
      <hoc-el-table
        title="表格Demo"
        :source="sourceList.data"
        :pagination="sourceList.pagination"
        :config="config"
        :loading="loading"
        :border="border"
        :height="tableHeight"
        :action-list="[
          { text: '固定表头', action: () => setFixedRow() },
          { text: '固定最右则列', action: () => setFixedRight() },
          { text: '居中表头label', action: () => setLabelCenter() },
          { text: '添加边框', action: () => setBorder() }
        ]"
        @getList="getList"
      >
      </hoc-el-table>
    </div>
  </div>
</template>

<script>

import TableChildrenA from './table-children-a'
import TableChildrenB from './table-children-b'

export default {
  components: {
    TableChildrenA,
    TableChildrenB
  },
  methods: {
    sleep (time = 1000) {
      return new Promise((resolve) => setTimeout(resolve, time))
    },
    async getList () {
      this.loading = true
      await this.sleep()
      this.loading = false
    },
    setFixedRight () {
      if (!this.fixedRight) {
        this.fixedRight = 'right'
      } else {
        this.fixedRight = false
      }
    },
    setFixedRow () {
      if (!this.tableHeight) {
        this.tableHeight = '350'
      } else {
        this.tableHeight = ''
      }
    },
    setLabelCenter () {
      if (!this.align) {
        this.align = 'center'
      } else {
        this.align = ''
      }
    },
    setBorder () {
      this.border = !this.border
    },
    setPublish (row) {
      this.$confirm(`此操作会将${row.name}发布到线上, 是否继续?`, `编号${row.id}提示`, {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$message({
          type: 'success',
          message: '发布成功!'
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消发布'
        })
      })
    },
    async setForbid (row) {
      this.loading = true
      await this.sleep()
      this.loading = false
      row.isForbid = !row.isForbid
    }
  },
  data () {
    return {
      loading: false,
      fixedRight: 'right',
      align: 'center',
      tableHeight: '350',
      border: false,
      sourceList: {}
    }
  },
  async created () {
    await this.getList()
    this.sourceList = this.mockData
  },
  computed: {
    mockData () {
      return {
        data: [
          { id: 0, name: '王小虎1', isForbid: false },
          { id: 1, name: '王小虎2', isForbid: false },
          { id: 2, name: '王小虎3', isForbid: false }
        ],
        pagination: {
          total: 3,
          pageSize: 10,
          currentPage: 1
        }
      }
    },
    config () {
      const self = this
      const align = self.align
      return [
        {
          attrs: {
            label: '编号',
            align,
            prop: 'id'
          }
        },
        {
          attrs: {
            label: '名称',
            prop: 'name',
            align,
            width: 200
          }
        },
        {
          attrs: {
            label: '状态',
            prop: 'isForbid',
            align,
            width: 200
          },
          // 渲染字符串,默认不想展示 prop 的值,而是想对它做一些处理的时候,可以用这个方法
          render (isForbid) {
            return isForbid ? '✖️禁用中' : '✔️非禁用'
          }
        },
        {
          attrs: {
            label: '详情A',
            align,
            width: 400
          },
          // 渲染组件,返回值为一个数组, data 作为组件的 v-model,适用于需要展示复杂的数据的场景
          renderComponent (row) {
            return [
              { name: 'TableChildrenA', data: row }
            ]
          }
        },
        {
          attrs: {
            label: '详情B',
            align,
            width: 400
          },
          renderComponent (row) {
            return [
              { name: 'TableChildrenB', data: row }
            ]
          }
        },
        {
          attrs: {
            label: '操作',
            width: '260',
            align,
            fixed: self.fixedRight
          },
          // 渲染 el-button,一般用在最后一列。目前只支持 el-button 和 click 事件,后续会根据需求支持任意的 el-xxx 和事件委托
          renderHTML (row) {
            return [
              {
                attrs: {
                  label: '查看',
                  type: 'text',
                  size: 'medium'
                },
                el: 'button',
                click () {
                  this.$message(JSON.stringify(row))
                }
              },
              {
                attrs: {
                  label: '编辑',
                  type: 'text',
                  size: 'medium'
                },
                el: 'button',
                click () {
                  this.$message(`编号${row.id} router -> 已跳转到编辑页面!`)
                }
              },
              {
                attrs: {
                  label: '发布',
                  type: 'text',
                  size: 'medium'
                },
                el: 'button',
                click () {
                  this.setPublish(row)
                }
              },
              !row.isForbid ? {
                attrs: {
                  label: '禁用',
                  type: 'text',
                  disabled: false,
                  size: 'medium'
                },
                el: 'button',
                click () {
                  this.setForbid(row)
                }
              } : {
                attrs: {
                  label: '解除禁用',
                  type: 'text',
                  disabled: false,
                  size: 'medium',
                  style: {
                    color: '#e6a23c'
                  }
                },
                el: 'button',
                click () {
                  this.setForbid(row)
                }
              }
            ]
          }
        }
      ]
    }
  }
}
</script>

<style>
* {
  padding: 0;
  margin: 0;
}
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}
</style>

<style lang="scss" scoped>
.box-container {
  .content {
    position: relative;
    padding: 20px 20px 0;
    margin: 0 auto;
  }
}
</style>

  • 示例 HocElAffix
<template>
  <div style="height: 200px; border: 1px solid #000;">占位</div>
  <hoc-el-affix
    :offsetTop="10"
  >
    <div class="demo"></div>
  </hoc-el-affix>
</template>
<style lang="scss" scoped>
.demo {
  width: 150px;
  height: 300px;
  border: 1px solid red;
}
</style>

  • 示例 HocElUploadSingle
<template>
  <hoc-el-upload-single
    action="your API"
    v-model="value"
  />
</template>
  • 示例 HocElUploadMultiple
<template>
  <hoc-el-upload-multiple
    action="your API"
    v-model="imageList"
  />
</template>
<script>
export default {
  data () {
    return {
      imageList: [
        { url: '' },
        { url: '' }
      ]
    }
  }
}
</script>
  • 示例 RuleForm
<template>
  <!-- code... -->
  <el-row :gutter="24">
    <el-col :span="24">
      <el-form-item
        label="标题"
        :prop="title"
        :rules="getRequiredRules('change')"
      >
        <el-input
          v-model="value.title"
          placeholder="请输入标题"
        />
      </el-form-item>
    </el-col>
  </el-row>
  <!-- code... -->
</template>
<!-- code... -->