我再也不想写 Form 和 Table 组件了💥|用一小时来开发提效小工具

简介: 我再也不想写 Form 和 Table 组件了💥|用一小时来开发提效小工具

我很烦


我的上一篇文章LowCode + 团队组件设计规范 = 灵光一闪 ?提到过,我有规范化标准化生产业务基础组件的想法。每次写这样一个组件差异也不是很大,每次都要有同样的 api,同样的 props,写多了就产生了厌烦。


没错,我就是一个很容易厌倦的工程师。好烦哦~

厌倦了怎么办呢,想办法解决啊。


没错,虽然我是一个很容易厌倦的工程师,但是我还是有这该死的责任感。好烦哦~

用技术手段,用可视化界面,去产生那些没啥营养的代码。


啊,我这该死的无处安放的魅力与中二气息。好烦哦,我好喜欢我自己「🐶 狗头」

所以,开搞开搞,整个编码过程大约一个小时,比较简单~


一小时编码


网络异常,图片无法展示
|


整体的思路就很简单:


网络异常,图片无法展示
|


在页面进行操作后生成中间数据,之后通过中间数据生成代码。下面我分别介绍 Form 和 Table 我分别写了什么。


Form

网络异常,图片无法展示
|


props:

  • disabled
  • disabledFileds

methods:

  • getData
  • setData
  • clearData
  • validate
  • clearValidate


数据结构:


Array.<{
    isInline: Boolean,
    label: String,
    key: String,
    type: String,
    required: Boolean
}>


作为表单要包含所有常见表单项:


typeoOtions: [{
    type: "RADIO",
  },{
    type: "CHECKBOX",
  },{
    type: "INPUT"
  }, {
    type: "INPUTNUMBER"
  }, {
    type: "SELECT"
  },{
    type: "CASCADER"
  },{
    type: "SWITCH"
  }, {
    type: "TIMEPICKER"
  }, {
    type: "DATEPICKER"
  }, {
    type: "DATETIMEPICKER"
  }, {
    type: "RATE"
  }, {
    type: "CUSTMER"
  }
],


生成代码的工具方法:


const optionTypes = [
  'RADIO',
  'CHECKBOX',
  'SELECT',
  'CASCADER',
];
const getFormItem = (schemaItem) => {
  switch (schemaItem.type) {
    case 'RADIO':
      return `<q-radio-group v-model="formData.${schemaItem.key}">
      <q-radio v-for=“(item, index) in ${schemaItem.key}Options” :key="index" :label="item.value" :disabled="disabledFields.includes('${schemaItem.key}')" >{{ item.label }}</q-radio>
    </q-radio-group>`;
    case "CHECKBOX":
      return `<q-checkbox-group v-model="formData.${schemaItem.key}">
      <q-checkbox v-for=“(item, index) in ${schemaItem.key}Options” :key="index" :label="item.value" :disabled="disabledFields.includes('${schemaItem.key}')" >{{ item.label }}</q-checkbox>
    </q-checkbox-group>`;
    case 'INPUT':
      return `<q-input v-model="formData.${schemaItem.key}" :placeholder="请输入${schemaItem.label}" :disabled="disabledFields.includes('${schemaItem.key}')" />`
    case 'INPUTNUMBER': 
      return `<q-input-number v-model="formData.${schemaItem.key}" :disabled="disabledFields.includes('${schemaItem.key}')" />`;
    case 'SELECT':
      return `<q-select v-model="formData.${schemaItem.key}" placeholder="请选择${schemaItem.label}" :disabled="disabledFields.includes('${schemaItem.key}')">
      <q-option
        v-for=“(item, index) in ${schemaItem.key}Options” 
        :key="index"
        :label="item.label"
        :value="item.value">
      </q-option>
    </q-select>
  `;
    case 'CASCADER':
      return `<q-cascader
        v-model="formData.${schemaItem.key}"
        :options="${schemaItem.key}Options"
        :disabled="disabledFields.includes('${schemaItem.key}')" 
      />`;
    case 'SWITCH':
      return `<q-switch
        v-model="formData.${schemaItem.key}"
        :disabled="disabledFields.includes('${schemaItem.key}')"
      />`;
    case 'TIMEPICKER':
      return `<q-time-select
        placeholder="请选择${schemaItem.label}"
        v-model="formData.${schemaItem.key}" 
        :disabled="disabledFields.includes('${schemaItem.key}')"
      />`
    case 'DATEPICKER':
      return `<q-date-picker
        type="date"
        placeholder="请选择${schemaItem.label}"
        v-model="formData.${schemaItem.key}" 
        :disabled="disabledFields.includes('${schemaItem.key}')"
      />`;
    case 'DATETIMEPICKER':
      return `<q-date-picker
        type="datetime"
        placeholder="请选择${schemaItem.label}"
        v-model="formData.${schemaItem.key}" 
        :disabled="disabledFields.includes('${schemaItem.key}')"
      />`;
    case 'RATE':
      return `<q-rate 
        v-model="formData.${schemaItem.key}" 
        :disabled="disabledFields.includes('${schemaItem.key}')"
      />`;
    case 'CUSTMER':
    default:
      return `<!-- dom: v-model=“formData.${schemaItem.key}” -->`;
  }
};
export const getFormCode = (schema) => {
  return `<template>
  <q-form
    ref="form"
    :model="formData"
    :rules="rules"
    :disabled="disabled"
  >
    ${
      schema.map(item => `<q-form-item label="${item.label}" prop="${item.key}" ${item.isInline?'class="inline-form-item"':''}>
        ${getFormItem(item)}
      </q-form-item>`).join('\n')
    }
  </q-form>                                   
  </template>
  <script>
  const getBaseCustomFormData = () => ({
    ${
      schema.map(item => `${item.key}: null`).join(',\n')
    }
  })
  export default {
  props: {
    disabled: {
      type: Boolean,
      default: false
    },
    // Array.<String>
    disabledFields: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      formData: getBaseCustomFormData(),
      ${
        schema.filter(item => optionTypes.includes(item.type)).map(item => `${item.key}Options: []`).join(',\n')
      },
      rules: {
        ${
          schema.filter(item => item.required).map(item => `
            ${item.key}: [
              { required: true, message: '请输入${item.label}', trigger: 'blur' }
            ]
          `).join(',\n')
        }
      },
    };
  },
  methods: {
    setData(data) {
      this.formData = Object.assign(getBaseCustomFormData(), data);
    },
    getData() {
      return Object.assign({}, this.formData);
    },
    clearData() {
      this.formData = getBaseCustomFormData();
    },
    validate() {
      return this.$refs.form.validate();
    },
    clearValidate () {
      this.$refs.form.clearValidate();
    },
  }
  };
  </script>
  <style lang="scss" scoped>
  .inline-form-item {
    display: inline-block;
    width: 50%;
    vertical-align: top;
  }
  </style>
  `
}


Table

网络异常,图片无法展示
|


props:

  • filter
  • selectable

methods:

  • reload
  • gotoFirstPage
  • getSelectionInfo
  • setSelectionInfo

event:

  • selectionChange


数据结构:


Array.<{
    type: 'normal'|'selection',
    prop: String,
    title: String,
    isCustmer: Boolean
}>


生成代码的工具方法:


const getTableColumn = (schemaItem) => {
  if(schemaItem.type == 'selection') {
    return `<pro-column 
      type="selection" 
      :selectable="selectable"
      :enable-cross-page-selection="false" 
    />`;
  } else if(schemaItem.isCustmer) {
    return `<pro-column prop="${schemaItem.prop}" title="${schemaItem.title}">
      <template #default="{ row }">
        {{ row.${schemaItem.prop} }}
      </template>
  </pro-column>`;
  } else {
    return `<pro-column prop="${schemaItem.prop}" title="${schemaItem.title}" />`;
  }
};
export const getTableCode = (schema) => {
  return `<template>
  <pro-table
    ref="table"
    :pagination-options="PAGE_OPTIONS"
    :fetch-data="fetchData"
    @selection-change="selectionChange"
  > 
    ${
      schema.map(item => `${getTableColumn(item)}`).join('\n')
    }
    <pro-column
      v-if="$slots.operation || $scopedSlots.operation"
      title="操作"
      prop="operation"
    >
      <template #default="{ row }">
        <slot name="operation" :row="row" />
      </template>
    </pro-column>
  </pro-table>
</template>
<script>
const PAGE_OPTIONS = {
  defaultPageSize: 20,
  pageSizeOptions: [10, 20, 50, 100],
  hideOnSinglePage: false,
};
export default {
  props: {
    filter: {
      type: Object,
      default: null,
    },
    ${
      schema[0]?.type == 'selection'? `selectable: {
        type: Function,
        default: () => true
      }`: ''
    }
  },
  watch: {
    filter: {
      deep: true,
      handler() {
        this.reload();
      },
    },
  },
  data() {
    return {
      PAGE_OPTIONS,
    };
  },
  methods: {
    async fetchData({ pagination }) {
      try {
      } catch (err) {
        this.$message.error("获取列表失败");
        return {
          total: 0,
          items: [],
        };
      }
    },
    selectionChange({selectedRows,isAll,exceptedRows}) {
      this.$emit('selectionChange', {selectedRows,isAll,exceptedRows});
    },
    reload() {
      this.$refs.table.reload();
    },
    gotoFirstPage() {
      this.$refs.table.gotoFirstPage(true);
    },
    getSelectionInfo() {
      return this.$refs.table.getSelectionInfo();
    },
    setSelectionInfo({ selectedRows, isAll, exceptedRows }) {
      this.$refs.table.setSelectionInfo({ selectedRows, isAll, exceptedRows });
    }
  },
};
</script>
`;
}


说不出再见


网络异常,图片无法展示
|


整片文章难度不高,但是可以提升自己的开发效率,就像我在我之前的年终总结「寒草呈献」我的肩上是风,风上是闪烁的星群✨|致直面焦虑与本心的 2021所说的,我们无法避免工作中存在重复,但是我们可以想办法去避免重复的劳作,使自己摆脱西西弗斯式的工作。


✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

君不见,黄河之水天上来,奔流到海不复回。
君不见,高堂明镜悲白发,朝如青丝暮成雪。
人生得意须尽欢,莫使金樽空对月。
天生我材必有用,千金散尽还复来。

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨


下一篇文章再会~


目录
打赏
0
0
0
0
3
分享
相关文章
如何在项目中使用CocoaPods和Carthage?
如何在项目中使用CocoaPods和Carthage?
88 4
YOLOv8改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
YOLOv8改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
542 1
YOLOv5改进 | 2023注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制)
YOLOv5改进 | 2023注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制)
546 0
webpack优化篇(四十):速度分析:使用 speed-measure-webpack-plugin
webpack优化篇(四十):速度分析:使用 speed-measure-webpack-plugin
2019 0
webpack优化篇(四十):速度分析:使用 speed-measure-webpack-plugin
如何使用Java语言快速开发一套智慧工地系统
使用Java开发智慧工地系统,采用Spring Cloud微服务架构和前后端分离设计,结合MySQL、MongoDB数据库及RESTful API,集成人脸识别、视频监控、设备与环境监测等功能模块,运用Spark/Flink处理大数据,ECharts/AntV G2实现数据可视化,确保系统安全与性能,采用敏捷开发模式,提供详尽文档与用户培训,支持云部署与容器化管理,快速构建高效、灵活的智慧工地解决方案。
126 0
前端的全栈之路Meteor篇(四):RPC方法注册及调用-更轻量的服务接口提供方式
RPC机制通过前后端的`callAsync`方法实现了高效的数据交互。后端通过`Meteor.methods()`注册方法,支持异步操作;前端使用`callAsync`调用后端方法,代码更简洁、易读。本文详细介绍了Methods注册机制、异步支持及最佳实践。
170 3
RE:从零开始的车载Android HMI(四) - 收音机刻度尺
本篇文章我们来研究如何绘制一个收音机的刻度尺。
373 0
实时计算 Flink版产品使用问题之基于宽表数据展示实时报表,该如何实现
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
Go 实战|使用 Wails 构建轻量级的桌面应用:仿微信登录界面 Demo
Wails 框架提供了一种简洁而强大的方式,让开发者能够利用 Go 的性能优势和 Web 前端的灵活性,从而能够使用更高效、更轻量级的方法来构建跨平台的桌面应用。本文探讨 Wails 框架的使用,从搭建环境到开发,再到最终的构建打包。
504 1
Go 实战|使用 Wails 构建轻量级的桌面应用:仿微信登录界面 Demo
淘宝订单接口在电商行业中的重要性及其实践
随着电子商务的快速发展,电商平台已经成为人们日常生活中不可或缺的一部分。淘宝作为中国最大的电商平台之一,拥有庞大的用户群体和商家资源。为了满足商家和消费者之间的交易需求,淘宝提供了丰富的API接口,其中订单接口是其中最为重要的一部分。本文将从理论到实践,深入探讨淘宝订单接口在电商行业中的重要性,并给出相应的代码实现。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问