一、插件开发上传插件

1.控件示图

2.使用vue ui新建项目 autoeltable,并且把elementUI安装配置项目

3.前端开发工具打开项目并把src修改examples,项目目录结构如下

4.在项目下新建package目录index.js用于存放控件

目录结构

下面是插件相关代码

package/autoeltable/AutoElTable.vue

<template>
  <div>
    <div v-for="(item, index1) in tableDatas" :key="index1">
      <el-collapse v-model="item.activeNames" style="border:1px solid #EBEEF5;">
        <el-collapse-item :name="item.id" :title="item.name">
          <template slot="title">
            <div @click="stopProp">
              <div style="display: inline-block;width: 100px;padding-left: 5px;">{{ item.name }}</div>
              <el-switch v-model="item.check" style="padding-left: 20px;" active-color="#004efc" inactive-color="#ff4949" />
            </div>
          </template>
          <div class="AUTO-common-layout-center">

            <div class="AUTO-common-layout-main AUTO-flex-main" style="border:1px solid #EBEEF5;">
              <div class="AUTO-common-head">
                <div class="AUTO-opts">
                  <slot name="left" />
                  <el-button v-show="item.isplan" type="primary" icon="el-icon-plus" :disabled="false" @click="handleAddEdit(item.tableLabel,item.tableData,item)">
                    新建
                  </el-button>
                  <el-button v-show="item.isplan" type="danger" icon="el-icon-delete" :disabled="false" @click="handleBatchRemoveDel(item)">
                    批量删除
                  </el-button>

                  <div v-show="item.build" style="display: inline-block;">
                    <el-select v-if="item.isAddColumn" v-model="item.colume" style="padding-left: 20px;" placeholder="请选择层级" @change="(val) => addColumn(val,item)">
                      <el-option
                        v-for="item in item.columeoptions"
                        :key="item.encode"
                        :label="item.fullName"
                        :value="item.encode"
                      />
                    </el-select>
                  </div>
                </div>

              </div>

              <el-form :ref="'formAuto_'+ item.id" :model="item" :rules="rule" :disabled="false">
                <el-table :ref="'table_'+item.id" :data="item.tableData.slice((item.cur_page-1)*item.pageSize,item.cur_page*item.pageSize)" border style="width: 100%" max-height="250" @selection-change="(val) => handleSelectionChange(val,item)">
                  <el-table-column v-if="item.tableLabel.length > 0" type="selection" :width="50" />
                  <el-table-column v-if="item.tableLabel.length > 0" type="index" :label="'序号'" :width="50" />
                  <el-table-column
                    v-for="(item, index) in item.tableLabel"
                    :key="AutoElTable"
                    :prop="item.prop"
                    :width="item.width"
                    :label="item.label"
                    align="center"
                  >
                    <template v-slot="scope">
                      <el-form-item :prop="`tableData[` + scope.$index + `].` + [item.prop]" :rules="rule[item.prop]" label-width="0">

                        <el-input v-if="item.type === 'string'" v-model="scope.row[item.prop]" />

                        <el-date-picker v-if="item.type === 'number'" v-model="scope.row[item.prop]" style="width: 100%;" type="date" format="yyyy-MM-dd" value-format="yyyy-MM-dd" />

                        <el-select v-if="item.type === 'array'" v-model="scope.row[item.prop]" style="width: 100%;" filterable clearable :multiple="item.multiple" collapse-tags>
                          <el-option v-for="item in item.option" :key="item.encode" :label="item.fullName" :value="item.encode" />
                        </el-select>

                        <el-switch v-if="item.type === 'switch'" v-model="scope.row[item.prop]" active-color="#004efc" inactive-color="#ff4949" />

                      </el-form-item>
                    </template>
                  </el-table-column>

                  <el-table-column
                    fixed="right"
                    label="操作"
                    width="120"
                  >
                    <template v-slot="scope">
                      <el-button type="danger" icon="el-icon-delete" @click.native.prevent="deleteRow(scope.$index, item.tableData)">
                        删除
                      </el-button>
                    </template>
                  </el-table-column>

                </el-table>
                <div class="pagination">
                  <el-pagination
                    background
                    :current-page="item.cur_page"
                    :page-sizes="item.pageSizes"
                    :page-size="item.pageSize"
                    layout="total, sizes, prev, pager, next, jumper"
                    :total="item.total"
                    @current-change="(val) => handleCurrentChange(item, val)"
                    @size-change="(val) => handleSizeChange(item, val)"
                  />
                </div>
              </el-form>
            </div>

          </div>

        </el-collapse-item>
      </el-collapse>
    </div>
  </div>
</template>

<script>
import { v4 as uuidv4 } from 'uuid'

export default {
  name: 'AutoElTable',
  components: {},
  props: {
    tableDatas: {
      type: Array,
      default: () => []
    },
    rule: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {}
  },
  created() {
    console.log(this.tableDatas, '初始化')
  },
  methods: {
    handleAddEdit(tableLabel, tableData, item) {
      const obj = {}
      for (let i = 0; i < tableLabel.length; i++) {
        const item1 = tableLabel[i].prop
        obj[item1] = undefined
        this.rule[item1] = tableLabel[i].rule
      }
      obj.id = uuidv4()
      tableData.push(obj)
      this.$nextTick(() => {
        this.$refs['table_' + item.id][0].bodyWrapper.scrollTop = this.$refs['table_' + item.id][0].bodyWrapper.scrollHeight
      })

      item.total = tableData.length
      const cur = item.total / item.pageSize
      item.cur_page = Math.ceil(cur)
    },
    deleteRow(index, tableData) { // eslint-disable-line no-unused-vars
      tableData = tableData.splice(AutoElTable, 1)
    },
    handleSelectionChange(val, item) {
      item.ids = val.map(item => item.id)
    },
    handleBatchRemoveDel(item) {
      if (!item.ids.length) {
        this.$message({
          type: 'error',
          message: '请选择一条数据',
          duration: 1500
        })
        return
      }
      item.ids.forEach(id => {
        item.tableData = item.tableData.filter((o) => {
          return o.id !== id
        })
      })
    },
    validateForm() {
      let flag = true
      this.tableDatas.forEach(item => {
        this.$refs['formAuto_' + item.id][0].validate((valid) => {
          if (!valid) {
            flag = false
          }
        })
      })
      return flag
    },
    handleSizeChange(item, val) {
      item.pageSize = val
      item.cur_page = 1
    },
    // 分页导航
    handleCurrentChange(item, val) {
      item.cur_page = val
    },
    addColumn(val, item) {
      item.columeoptions.forEach(o => {
        if (o.encode === val) {
          item.tableLabel = []
          for (let i = 0; i < Number(o.encode); i++) {
            const obj = { width: '', type: 'string' }
            obj.label = this.changeNumToHan(i + 1) + o.company
            obj.prop = o.encode + '_' + i
            item.tableLabel.push(obj)
          }
        }
      })
    },
    // 阻止冒泡事件
    stopProp(e) {
      e.stopPropagation()
    },
    changeNumToHan(num) {
      const arr1 = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
      const arr2 = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万', '十', '百', '千', '亿']// 可继续追加更高位转换值
      if (!num || isNaN(num)) {
        return '零'
      }
      const english = num.toString().split('')
      let result = ''
      for (let i = 0; i < english.length; i++) {
        const des_i = english.length - 1 - i// 倒序排列设值
        result = arr2[i] + result
        const arr1_index = english[des_i]
        result = arr1[arr1_index] + result
      }
      // 将【零千、零百】换成【零】 【十零】换成【十】
      result = result.replace(/零([千百十])/g, '零').replace(/十零/g, '十')
      // 合并中间多个零为一个result = result.replace(/零+/g, '零')
      // 将【零亿】换成【亿】【零万】换成【万】
      result = result.replace(/零亿/g, '亿').replace(/零万/g, '万')
      // 将【亿万】换成【亿】
      result = result.replace(/亿万/g, '亿')
      // 移除末尾的零
      result = result.replace(/零+$/, '')
      // 将【零一十】换成【零十】
      // result = result.replace(/零一十/g, '零十');//貌似正规读法是零一十
      // 将【一十】换成【十】
      result = result.replace(/^一十/g, '十')
      return result
    }
  }
}
</script>
<style lang="scss" scoped>

.AUTO-common-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 10px;
  flex-shrink: 0;

  .AUTO-common-head-right {
    flex-shrink: 0;
    font-size: 0;

    .el-link {
      margin-left: 12px;
    }

    .AUTO-common-head-icon {
      color: #606266;
    }
  }
}

.AUTO-common-layout-center {
  flex: 1;
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;

  .AUTO-common-layout-main {
    flex: 1;
    background-color: #fff;
    height: 100%;
    overflow: hidden;

    &amp;.nohead {
      padding-top: 10px;
    }
  }
}

.AUTO-flex-main {
  display: flex;
  flex-direction: column;

  .el-table {
    flex: 1;

    &amp;::before {
      border-bottom: 0;
      height: 0
    }
  }

  .el-table__fixed::before,
  .el-table__fixed-right::before {
    border-bottom: 0;
    height: 0
  }
}

.AUTO-opts {
  display: inline-block;
}

::v-deep .el-table thead tr {
  background-color: #FFFFFF !important;
}

::v-deep .el-table thead tr th {
  background-color: #FFFFFF !important;
}

::v-deep .el-collapse-item__header {
  padding-left: 10px;
}

::v-deep .el-form-item--mini.el-form-item, .el-form-item--small.el-form-item {
  margin-bottom: 0;
}

::v-deep .el-form-item--small .el-form-item__error {
  margin-bottom: 20px;
}

::v-deep .el-form-item.is-error {
  margin-bottom: 20px
}

::v-deep .el-pagination {
  padding: 10px 15px;
}

::v-deep .el-collapse-item__content {
  padding-bottom: 0;
}

.pagination {
  background: #fff;
  text-align: right;
}

.pagination.hidden {
  display: none;
}

</style>

package/auto-el-table/index.js

// 引入组件
import AutoElTable from './AutoElTable'

// 为组件提供 install 安装方法,供按需引入
AutoElTable.install = (Vue) => {
  Vue.component(AutoElTable.name, AutoElTable)
}

// 导出组件
export default AutoElTable

package/index.js

import AutoElTable from './auto-el-table'
// 存储组件列表
const components = [
  AutoElTable
]
/*
  定义install 方法接收Vue作为参数,如果使用use注册插件,则所有的组件都将被注册
*/
const install = function(Vue) {
  // 判断是否安装
  if (install.installed) { return }
  // 遍历所有组件
  components.map(item => {
    Vue.component(item.name, item)
  })
}
// 判断是否引入文件
if (typeof window !== 'undefined' &amp;&amp; window.Vue) {
  install(window.Vue)
}
export default {
  install,
  AutoElTable
}

5.修改package.json文件,文件内容如下

name:插件名称

version:版本号

private:这个必须为false,否则npm发布不了的

main:执行lib命令后,生成插件的js

author:作者

lib:生成插件源码编译命令

vue-cli-service build --target lib --name auto-el-table --dest lib packages/index.js

这里插件源码已生成,下一步就是登录npm并且上传插件了,注意需要在项目下增加.npmignore文件,文件内容

.npmignore

# 忽略目录
packages/
public/
node_modules/
.idea/
.git/

# 忽略指定文件
vue.config.js
babel.config.js
*.map

需要增加vue.config.js文件

vue.config.js

module.exports = {
  // 扩展 webpack 配置,使 packages 加入编译
  // chainWebpack一个函数,会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部webpack 配置进行更细粒度的修改
  chainWebpack: config => {
    config.module
      .rule('js')
      .include
      .add(__dirname + 'packages') // 注意这里需要绝对路径,所以要拼接__dirname
      .end()
      .use('babel')
      .loader('babel-loader')
      .tap(options => {
        // 修改它的选项...
        return options
      })
  }
}

6.切换npm源为官方

npm config set registry http://registry.npmjs.org

7.登录npm

npm login 

8.上传插件

npm publish

9.此时就可以npm官网查询对应的插件了。

二、使用插件

1.项目中安装插件,因为此插件是基于elementui开发的,所以只适合elementui框架的项目使用。

npm i auto-el-table

2.main.js引入插件

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'
Vue.config.productionTip = false


import AutoElTable from 'auto-el-table'//引入插件
import 'auto-el-table/lib/auto-el-table.css' // 引入相关样式

Vue.use(AutoElTable)

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

3.页面引入标签直接使用

<template>
  <div class="hello">
    <auto-el-table ref="subComp" :table-datas="tableDatas" :rule="formRules" ></auto-el-table>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {
      tableDatas: [
        {
          tableData: [],
          tableLabel: [
            { label: '一层', width: '', prop: '1_1', type: 'string' }
          ],
          id: '100101',
          name: '机房温度℃',
          activeNames: ['100101'],
          check: false,
          infoData: {},
          cur_page: 1,
          pageSize: 10,
          total: 0,
          pageSizes: [10, 20, 30, 50],
          isAddColumn: true,
          colume: undefined,
          columeoptions: [{ encode: '1', fullName: '一层', company: '层' }, {
            encode: '2',
            fullName: '二层',
            company: '层'
          }],
          isplan: false,
          build: true
        },
        {
          tableData: [],
          tableLabel: [{ label: '艾默生开关电源', width: '', prop: '1_1', type: 'string' }],
          id: '100102',
          name: '开关电源负载',
          activeNames: ['100102'],
          check: false,
          infoData: {},
          cur_page: 1,
          pageSize: 10,
          total: 0,
          pageSizes: [10, 20, 30, 50],
          isplan: false
        },
        {
          tableData: [],
          tableLabel: [
            {
              label: '传输设备运行',
              width: '',
              prop: '1_1',
              type: 'array',
              option: [{ encode: '1', fullName: '正常' }, { encode: '2', fullName: '停用' }]
            },
            {
              label: '交换设备运行',
              width: '',
              prop: '1_2',
              type: 'array',
              option: [{ encode: '1', fullName: '正常' }, { encode: '2', fullName: '停用' }]
            },
            {
              label: '网络设备运行',
              width: '',
              prop: '1_3',
              type: 'array',
              option: [{ encode: '1', fullName: '正常' }, { encode: '2', fullName: '停用' }]
            },
            {
              label: '电源设备运行',
              width: '',
              prop: '1_4',
              type: 'array',
              option: [{ encode: '1', fullName: '正常' }, { encode: '2', fullName: '停用' }]
            },
            {
              label: '空调设备运行',
              width: '',
              prop: '1_5',
              type: 'array',
              option: [{ encode: '1', fullName: '正常' }, { encode: '2', fullName: '停用' }]
            }
          ],
          id: '100103',
          name: '设备运行状况',
          activeNames: ['100103'],
          check: false,
          infoData: {},
          cur_page: 1,
          pageSize: 10,
          total: 0,
          pageSizes: [10, 20, 30, 50],
          isplan: true
        },
        {
          tableData: [],
          tableLabel: [
            { label: '当前正向有功总需量kw', width: '', prop: '1_1', type: 'string' },
            { label: '当前组合无功总电量kvan h', width: '', prop: '1_2', type: 'string' },
            { label: '有功峰电量kw h', width: '', prop: '1_3', type: 'string' },
            { label: '有功平电量kw h', width: '', prop: '1_4', type: 'string' },
            { label: '有功谷电量kw h', width: '', prop: '1_5', type: 'string' },
            { label: '有功总电量kw h', width: '', prop: '1_6', type: 'string' }
          ],
          id: '100104',
          name: '五道口电表电量',
          activeNames: ['100104'],
          check: false,
          infoData: {},
          cur_page: 1,
          pageSize: 10,
          total: 0,
          pageSizes: [10, 20, 30, 50],
          isplan: false
        },
        {
          tableData: [],
          tableLabel: [
            { label: '当前正向有功总需量kw', width: '', prop: '1_1', type: 'string' },
            { label: '当前组合无功总电量kvan h', width: '', prop: '1_2', type: 'string' },
            { label: '有功峰电量kw h', width: '', prop: '1_3', type: 'string' },
            { label: '有功平电量kw h', width: '', prop: '1_4', type: 'string' },
            { label: '有功谷电量kw h', width: '', prop: '1_5', type: 'string' },
            { label: '有功总电量kw h', width: '', prop: '1_6', type: 'string' },
            { label: '路电表1', width: '', prop: '1_7', type: 'string' },
            { label: '路电表2', width: '', prop: '1_8', type: 'string' }
          ],
          id: '100105',
          name: '西直门电表电量',
          activeNames: ['100105'],
          check: false,
          infoData: {},
          cur_page: 1,
          pageSize: 10,
          total: 0,
          pageSizes: [10, 20, 30, 50],
          isplan: false
        },
        {
          tableData: [],
          tableLabel: [
            { label: '1-A', width: '', prop: '1_1', type: 'string' },
            { label: '1-B', width: '', prop: '1_2', type: 'string' },
            { label: '1-C', width: '', prop: '1_3', type: 'string' },
            { label: '2-A', width: '', prop: '1_4', type: 'string' },
            { label: '2-B', width: '', prop: '1_5', type: 'string' },
            { label: '2-C', width: '', prop: '1_6', type: 'string' }
          ],
          id: '100106',
          name: '120K-UPS',
          activeNames: ['100106'],
          check: false,
          infoData: {},
          cur_page: 1,
          pageSize: 10,
          total: 0,
          pageSizes: [10, 20, 30, 50],
          isplan: false
        }
      ],
      formRules: {}
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

4.插件还有很多不足,是第一次开发npm插件,还需要大家多多指正。

原文地址:https://blog.csdn.net/sinat_34671799/article/details/127859461

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_48334.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注