The introduction

Recently, it has been found that various large/small factories are developing their own form generator/low code platform to improve the efficiency of development. This article will take you to write a first version of vUE form generator.

The demo link sutianbinde. Making. IO/vue – form – re…

Making source github.com/sutianbinde…

It is recommended to speed read for 5-10 minutes and follow the development time for 3-5 hours

implementation

1. Generate the project using vue-CLI (for steps that are not technical points in this article, these steps are abbreviated below)

The vue2. X version for our sample project

2. Install Element, Sass-Loader, and sass and start the project

This demo renders components based on Element and will be updated to support other libraries.

3. Use element UI for basic layout

Here, the main components are divided into three left, middle and right components, and our subsequent code is implemented in these three components.

The basic directory structure is as follows:

4. In left. vue, define the basic form components and render them as buttons as shown above

Json format

ComponentList: [{label: "input ", Component: "ElInput"}, {label:" selector ", Component: "ElSelect"}, {label: "ElSelect"}, {label: {label: "ElCheckbox"}, {label: "ElCheckbox"}, {label: "date picker ", Component: "ElDatePicker" } ]Copy the code

5. When clicking or dragging ends, pass the component name to the middle. Vue component and generate the component schema data.

The following is an example of component Schema data:

$id: $id: $id: $id: $id: $id: $id: $id: $id: $id: $id: "ElSelect_" + math.floor (math.random () * 1000), // Get the key propValue of the form v-model data in the future: {// Props value that needs to be bound to the form component: "", / / demo binding v - key model. Enums: [" a", "b", "c"), / / the value of the option enumNames: [" early ", "in", "late"] / / the name of the option}}, {component: "ElRadio", label: "Form label", $ID: "ElRadio_" + math.floor (math.random () * 1000), propValue: {value: "", enums: [" a ", "b", "c"], enumNames: [" early ", "in", "late"]}}].Copy the code

How can we render a form component using the vue component to render the corresponding component

  <component
    :is="item.component"
    v-bind="item.propValue"
    v-model="item.propValue.value"  />
Copy the code

However, some of Element’s form components are multi-label, and a single label does not render the entire component. In this case, we need to rewrite these components, such as the ElSelect component, so that we render them as we rewrite them.

The rewrite strategies are as follows: 1. Inherit and pass all props; 2. Respond to all events; 3

Let’s create a new folder widgets to write the components that need to be redone. In the sample project, we just rewrote two components.

A sample rewrite of select.vue

<script> import { Select } from "element-ui"; export default { props: { enums: { type: Array, default: () => [] }, enumNames: { type: Array, default: () => [] }, ... Select.props }, render() { return ( <el-select {... { props: this.$props, on: this.$listeners }}> {this.enums.map((val, index) => { return <el-option value={val} label={this.enumNames[index]} />; })} </el-select> ); }}; </script><style></style>Copy the code

We then need to import and register this component in middle. Vue so that when meddle.vue encounters an ‘ElSelect’ component, it will be rendered as a rewritten component.

...
import ElSelect from "../widgets/select.vue";
import ElRadio from "../widgets/radio.vue";
export default {
  components: {
    ElSelect,
    ElRadio
  },
  ...
Copy the code

After the component is rendered, it looks like this (the basic layout outside the component is not listed here).

6. When clicking the form, select, delete, copy, move and other functions can be realized

Select: here we listen for native click events of the form item.

<el-form-item
  :label="item.label"
  @click.native="selectCurComponent($event, item)">
  <component
    :is="item.component"
    v-bind="item.propValue"
    v-model="item.propValue.value"
  />
</el-form-item>
Copy the code

Delete, copy, and move just by manipulating the componentData array in the Schema format.

7. Edit properties in right.vue according to the selected item

The component property of the selected item allows you to get the original component of the Element. If you find that component, you can get all props.

import ElementUI from "element-ui"; // The ElementUI component key does not contain 'El'. For example, the ElSelect key in the ElementUI object is 'Select', so the first two digits are cut off. // If you want to adapt to different component libraries, the component prefix should be added at rendering time. All the default added El ElementUI [this.activeItem.com ponent. Slice (2). Props;Copy the code

8. Handle the deletion and addition of Select/Radio options

When we generate shema, we default to the initial value enums and the option name enumNames,

In right.vue, we generate two drop-down boxes for adding new options based on these two arrays, so that options can be entered manually, and finally the selected items are set as the result to the schema data of the form data in middle-vue.

Basic code Examples

// When setting data in right.vue, set nums to the corresponding key, this.enumoptions = defaultProps. Enums; this.enumValue = defaultProps.enums; this.enumNameOptions = defaultProps.enumNames; this.enumNameValue = defaultProps.enumNames; </div><el-select V-model ="enumValue" multiple filterable allow-create Default-first-option placeholder=" @change="valueChange('enums', $event)"> <el-option v-for="item in enumOptions" :key="item" :label="item" :value="item" ></el-option></el-select><div> Option name :</div><el-select V-model ="enumNameValue" multiple filterable allow-create Default-first-option placeholder=" please select @change="valueChange('enumNames', $event)"> <el-option v-for="item in enumNameOptions" :key="item" :label="item" :value="item" ></el-option></el-select> ValueChange (key, value) {this.$emit("change", key, value); } // the change event was received in app.vue, And call the middle. The method / / in the middle of the vue. Vue corresponds to changes in the value of the changeProps (key, value) {enclosing $set (this. ActiveItem. PropValue, key, value); }Copy the code

9, Right.vue props = input () and checkbox (); after rendering, listen for the input and change events, and change the propValue of the corresponding component schema data in middle.

The basic process is the same as 8

10. View and copy schemas.

The schema generated for production should consist of two parts, one for form data and the other for binding v-Model, as shown in the following example

{" schema ": [{" component" : "ElSelect", "label" : "form the label", "$id" : "ElSelect_944", "propValue" : {" enums ": [" a ", "b", "c"], "enumNames" : [" early ", "in", "late"]}}, {" component ":" ElRadio ", "label" : "form the label", "$id" : "ElRadio_609", "propValue" : {" enums ": [" a", "b", "c"], "enumNames" : [" early ", "in", "late"]}}], "model" : { "ElSelect_944": "", "ElRadio_609": "" } }Copy the code

In the demo example, the schema data is displayed directly in the Pre tag and copied using Document.execcommand (“copy”).

Logical comparison to submit a bill, can go to the warehouse code to view.

11. How to use schema after it is generated.

We need to write a generic Render component that, in a real project, will generate the corresponding form as soon as the schema data is passed in

</render- Components :componentData="schema" // form render data :model="model" // form binding value ></render- Components >Copy the code

12. Write render- Components based on this usage. The basic logic is to use components to iterate and render the form schema out of the form, internally register covered components, and bind the corresponding V-Model.

<template> <el-form ref="ruleForm" label-width="100px" class="demo-ruleForm" :model="model" > <el-form-item v-for="(item, index) in componentData" :key="index" :label="item.label" > <component :is="item.component" v-bind="item.propValue" v-model="model[item.$id]" /> </el-form-item> </el-form> </template> <script> import ElSelect from ".. /widgets/select.vue"; import ElRadio from ".. /widgets/radio.vue"; export default { components: { ElSelect, ElRadio }, props: { componentData: { type: Array, default: () => [] }, model: { type: Object, default: () => ({}) } }}; </script> <style lang="scss" scoped>.demo-ruleForm { flex: 1; }</style>Copy the code

Follow-up plans…

The above form generator is only a demo version. If it is to be used in the actual production environment, it needs to re-plan the organizational structure, verify the schema format, implement different rendering logic in the grouping library, implement the internal linkage logic and verification mechanism of the form, and provide third-party registration API. There may be another project to implement the Pro version.

Post title XXX | creator training camp The campaign is under way…