“This is the first day of my participation in the First Challenge 2022. For details: First Challenge 2022.”

preface

Since 2016, the concept of low code began to rise in China. In that year, there were a total of 10 financing events in the industry. After that, the number of financing cases in the industry showed an overall upward trend, and increased to 14 cases in 2020, including 13 cases of financing over 100 million yuan.

In terms of the distribution of financing rounds, angel round, seed round, A round and B round financing accounted for 50% in 2016, while by 2020, the proportion will reach 78.6%, an increase of 28.6% compared with 2016. This shows that the low code market as a whole is still in its infancy.

In 2021 many companies, large and small, will start developing low-code platforms. Low code is the ability to quickly build an application by “dragging and dropping” with little or no code. So for developers, how do we get started?

“Drag” implementation

The key word is “drag and drop”. In fact, the interaction mode of “drag and drop” has existed in the era of Jquery. There are two main front-end implementations of drag and drop

  1. Draggable and Droppable, represented by jQUERy-UI, are based on mouse events mousedown, Mousemove, mouseup or touch events touchStart, TouchMove, touchEnd. Record the start and end positions to drag and drop the passing data.

  2. Through the HTML5 Drag and Drop API

Here is the simple implementation code

<script>
function dragstart_handler(ev) {
 // A Adds the id of the target element to the data transfer object
 ev.dataTransfer.setData("application/my-app", ev.target.id);
 ev.dataTransfer.effectAllowed = "move";
}
function dragover_handler(ev) {
 ev.preventDefault();
 ev.dataTransfer.dropEffect = "move"
}
function drop_handler(ev) {
 ev.preventDefault();
 // Get the target'S ID and add the moved element to the target's DOM
 const data = ev.dataTransfer.getData("application/my-app");
 ev.target.appendChild(document.getElementById(data));
}
</script>

<p id="p1" draggable="true" ondragstart="dragstart_handler(event)">This element is draggable.</p>
<div id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Zone</div>
Copy the code

More advanced: The Drop API also supports dragging and dropping files directly from the system desktop to the browser, using datatransfer.files for drag-and-upload.

React-dnd

React DnD is a set of React tools created by React and Redux core author Dan Abramov to help you build complex drag-and-drop interfaces while keeping components decoupled. React DnD, for example, doesn’t provide a sorting component; instead, it gives you the tools you need.

The official demo

Let’s look at a simple implementation

The first step is to set up the drag-and-drop implementation at the project root node

import { render } from 'react-dom'
import Example from './example'
import { DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'

function App() {
    return (
      <div className="App">
        <DndProvider backend={HTML5Backend}>
          <Example />
        </DndProvider>
      </div>)}Copy the code

React-dnd-touch-backend is used for mobile phones, because react-DNd-HTML5-backend does not support touch

The realization of the DragBox

import { useDrag } from 'react-dnd';
import { ItemTypes } from './ItemTypes';
const style = {
    cursor: 'move'
};
export const Box = function Box({ name }) {
    const [{ isDragging }, drag] = useDrag(() = > ({
        type: ItemTypes.BOX,
        item: { name },
        end: (item, monitor) = > {
            const dropResult = monitor.getDropResult();
            if (item && dropResult) {
                alert(`You dropped ${item.name} into ${dropResult.name}! `); }},collect: (monitor) = > ({
            isDragging: monitor.isDragging(),
            handlerId: monitor.getHandlerId(),
        }),
    }));
    const opacity = isDragging ? 0.4 : 1;
    return (<div ref={drag} style={{ . style.opacity}} >{name}</div>);
};
Copy the code
  • Here,typeIs a string used to constrain the relationship between drag and drop components. Events cannot be called back if the strings are inconsistent, mainly to avoid multiple instances of drag and drop on a page
  • itemThat’s the data that’s being passed as you drag
  • endThis is the callback after the drag and drop
  • collectUsed to get the state of the drag, you can set the style

DropContainer implementation

import { useDrop } from 'react-dnd';
import { ItemTypes } from './ItemTypes';

const style = {
    ...
};
export const DropContainer = () = > {
    const [{ canDrop, isOver }, drop] = useDrop(() = > ({
        accept: ItemTypes.BOX,
        drop: () = > ({ name: 'Dustbin' }),
        collect: (monitor) = > ({
            isOver: monitor.isOver(),
            canDrop: monitor.canDrop(),
        }),
    }));
    const isActive = canDrop && isOver;
    let backgroundColor = '# 222';
    if (isActive) {
        backgroundColor = 'darkgreen';
    }
    else if (canDrop) {
        backgroundColor = 'darkkhaki';
    }
    return (<div ref={drop} role={'Dustbin'} style={{ . style.backgroundColor}} >
			{isActive ? 'Release to drop' : 'Drag a box here'}
        </div>);
};
Copy the code
  • typeSame type as drag
  • dropThe drag end function returns the data to place the node
  • collectThe state used to obtain the drag state, which can be styled

Low code implementation

Back to our low-code topic, let’s take a look at some of the best page designs that can be nailed down

It is mainly divided into three areas: left component area, middle design area and right editing area. Does the left component area and the design area in the middle look similar to the official React-DND demo?

Define the JSON

Next we will:

  • Defines component types that can be dragged
  • The rendering component for each component type
  • Property Settings for each component

Let’s define a few draggable fields. For example, the most basic data types, div, H1, and P tags are all components. Let’s define the following field types.

const fields= [
  {
    type: 'div'.props: {
      className: ' ',}}, {type: 'h1'.props: {
      className: 'text-3xl'.children: 'H1',}}, {type: 'p'.props: {
      className: ' '.children: 'paragraph 111',}}... ]Copy the code

For these drag fields, we need to have rendered components. For div, H1, p these are the tags themselves, but we need to encapsulate them with React

const previewFields = {
  div: (props: any) = > <div {. props} / >,
  h1: (props: any) = > <h1 {. props} / >,
  p: (props: any) = > <p {. props} / >. }Copy the code

Configurable field for the right border region

const editAreaFields = {
    div: [{key: 'className'.name: 'the style'.type: 'Text'],},h1: [{key: 'children'.name: 'content'.type: 'Text'],},p: [{key: 'children'.name: 'content'.type: 'Text'}, {key: 'className'.name: 'the style'.type: 'Text',},],... }Copy the code

The above fields indicate that div can set only className, H1 can set only content, and P tag can set both content and className. The right-hand side can also be configured with different components, such as Text rendering to the simplest Input.

Nested drag

Basic components can be nested, such as the one I want to drag to create the page below

I actually need to generate a JSON tree and render the page from that tree.

Each time you drag, you can generate a UUID and then use depth-first traversal tree data from the root node to the leaf node from top to bottom. Place the component and then manipulate the data

export const traverse = <T extends { children?: T[] }>( data: T, fn: (param: T) => boolean ) => { if (fn(data) === false) { return false } if (data && data.children) { for (let i = data.children.length - 1; i >= 0; i--) { if (! traverse(data.children[i], fn)) return false } } return true }Copy the code

Rich component

Open source components can be used, integrated into low code, we just need to define the right side edit area and the left side field data, such as integrating @ant-Design/Charts now

In the bar diagram, for example, we define the drag field data

{
type: 'Column'.module: '@ant-design/charts'.h: 102.displayName: 'Bar chart component'.props: {
  xField: 'name'.yField: 'value'.data: [{name: 'A'.value: 20}, {name: 'B'.value: 60}, {name: 'C'.value: 20,}]},Copy the code

Render directly using import {Column} from ‘@ant-design/charts’; Props adds default data to render a nice histogram directly.

Then add a data editing component and the final result is shown below

The generated code

With the JSON tree, we can also generate the view code we want. Component type + props + subcomponent data, and the code for each node is concatenated from this string.

<${sub.type}${props}>${children}</${sub.type}>

Props can also be spliced as key=value. Data is traversed in a depth-first manner from the bottom up of the tree from the leaf to the root node.

Code formatting

Prettier can be used to format code, putting the logic for formatting code into a webWork

importScripts('https://unpkg.com/[email protected]/standalone.js');
importScripts('https://unpkg.com/[email protected]/parser-babel.js');

self.addEventListener(
  'message'.function (e) {
    self.postMessage(
      prettier.format(e.data, {
        parser: 'babel'.plugins: prettierPlugins,
      })
    );
  },
  false
);
Copy the code

preview

In addition to the SRC attribute of iframe, HTML5 has also added a new attribute, srcdoc, which is used to render a piece of HTML code into the iframe

iframeRef.value.contentWindow.document.write(htmlStr)
Copy the code

The effect

Drag a table and a bar chart

Look at the code

Github and the preview address are attached

  • 📕 Warehouse address: github.com
  • 📗 preview address: low-code.runjs.cool

summary

A simple, low-code implementation of local logging is simply summarized as drag and drop -> JSON Tree -> page

But there’s still a long way to go before it’s actually productive, like

  • Component data binding and linkage
  • As the number of components increases, components need to be servitized and dynamically deployed
  • The component developer’s cost versus the upstart cost of the maintainer
  • Component templating
  • Page deployment and production

Any of the above points may cost a lot of money. In my opinion, there are several ways for low code and low cost to be put into production

1. Similar to mall-Cook H5 construction

2. Similar to jSON-editor form construction

At the end of this article, the thinking and discussion of low code scaffolding may not be complete enough, welcome to discuss and supplement. I hope this article was helpful to you, and you can also refer to my previous articles or share your thoughts and insights in the comments section.