头图

How to design and implement H5 marketing page building system

前端森林
中文

background

In recent years, low code , no code , pro code etc. have increasingly appeared in our field of vision. With a mindset not to be drawn, I decided to explore it in depth.

I am in the marketing department. Every day/month carries a large number of marketing activities, this article is also some of my experience in the process of exploring visualization construction

In fact, these nouns are related to the building. One of the most widely used scenarios is marketing. We know that whether it is e-commerce giants such as Taobao and Jingdong, or OTA such as Ctrip and Qunar, countless activity pages continue to be carried on the APP every day.

Roughly sort out some of the characteristics of marketing activities:

  • Similar pages: page layout and business logic are relatively fixed
  • High frequency of demand: There are multiple such demands every week or even every day
  • Fast iteration: short development time, tight launch time
  • Time-consuming development: repetitive development tasks, consuming communication time and manpower from all parties

Different from regular business development, marketing activities are often affected by many factors: holiday promotions, policy rules, etc., so it may be the activity mentioned this morning, and it will be carried out tomorrow. If you rely solely on front-end classmates to maintain, you don’t have to add countless classes (such as me before)

Every time I come to a new event, I rely on front-end classmates to draw the page. Obviously, this efficiency is extremely low. If the schedule is more generous, if you encounter 618 Double 11, I’m afraid it’s not going to drive us crazy. .

Floor construction

In view of this scenario, a lot of internal discussions have also been held. The unanimous conclusion reached is that the development students provide marketing to build the backend, the page is made configurable, and the configuration work is left to the product/operation students. In this way, the building a marketing page based on the 160ed01c37ab52 floor came into being.

In fact, building the floor in the marketing page is a relatively common way.

The picture above is an event page of JD.com. The page is mainly composed of three parts: the first picture floor, the coupon floor, and the hot sale floor. Because it is like building a building in life, in the early marketing construction, there is the concept floor. Each floor actually corresponds to a specific component.

Then you can upload the corresponding data in edit content area of the specific floor.

But this method has a big disadvantage: it is not intuitive. With the rapid iteration of the business, some feedback has been received one after another. In the end, I found that what the operating students really need is the kind of page that can be directly dragged and dropped, that is, the visualization building

Visualized construction

floor building, it was further transformed into a visualized building, which increased the complexity a lot. Simply looking at the different presentations of the page may just add a drag operation. But when I was really ready to land, I found that there were a lot of details, and it also contained a lot of design concepts.

Let's take a look at the prototype diagram first, and then carefully analyze what needs to be done:

Most of the marketing visualization building systems on the market are basically presented on a page similar to the above picture. The left side corresponds to the component area, the middle is the canvas area, and the right is the attribute area.

The general operation flow is to drag the component on the left to the canvas in the middle, select the component, and the property panel on the right will display the properties associated with the component. Edit the properties on the right, and the corresponding component styles in the canvas will be updated synchronously. Page splicing is complete, you can preview the page If the preview is correct, you can publish the publish button.

After sorting out the process, let’s take a look at the project’s infrastructure:

Here I pave the function of the project design based on the prototype. In fact, it is still centered on the component, the canvas, and the property panel.

Here, we think about a few questions:

  • How to render the components that have been added to the canvas in the canvas area (there are many component library components, maybe only a few components need to be added to the canvas, consider how to do dynamic rendering)?
  • Drag the component into the canvas area from the left, select the component, you can know the attributes associated with the component. How to design the component schema?
  • Can the canvas area and the component rendering during preview share a set of rendering logic?
  • How to maintain the component data (consider scenarios such as adding components, deleting components, component rendering/preview, etc.)
  • How to maintain the component library (consider scenarios where new components meet business needs)

Let’s first look at the first one. A simple summary is that dynamically loads components.

Dynamically load components

If you often use vue , then I think you are no vue to the dynamic component :

<!-- 当 currentView 改变时组件就改变 -->
<component :is="currentView"></component>

Most editors on the market also use this feature, and the general idea is:

  • Use an array componentData maintain the data in the editor
  • When dragging the component to the canvas, the data of this component push into componentData
  • The editor traverses ( v-for ) component data componentData and renders the components to the canvas in turn

Since my team, including myself, has been using react , I will focus on the implementation of dynamic loading react umi .

When I was implementing this part of the function, I found umi in api of dynamic :

Encapsulate an asynchronous component:

const DynamicComponent = (type, componentsType) => {
  return dynamic({
    loader: async function () {
      const { default: Component } = await import(
        `@/libs/${componentsType}/${type}`
      );
      return (props) => {
        return <Component {...props} />;
      };
    },
  });
};

Then when calling, just pass in the component array:

const Editor = memo((props) => {
  const {
    componentData,
  } = props;
  return (
    <div>
      {componentData.map((value) => (
        <div
          key={value.id}
        >
          <DynamicComponent {...value} />
        </div>
      ))}
    </div>
  );
});

The first problem is solved, let's look at the second one, which is: How to design the component schema?

Component Schema design

This involves the linkage of the components, canvas, and attribute area. It mainly contains form attributes and initial values that are strongly related to the component.

Due to the field limitation and verification of component properties, in order to standardize and avoid errors, it is recommended that the project use ts

Here is a TabList component as an example to show its Schema structure:

const TabList = {
  formData: [
    {
      key: 'tabs',
      name: 'Tab名称',
      type: 'TitleList',
    },
    {
      key: 'layout',
      name: '布局方式',
      type: 'Select',
      options: [
        {
          key: 'single',
          text: '单列',
        },
        {
          key: 'double',
          text: '双列',
        },
      ],
    },
    {
      key: 'activeColor',
      name: '激活颜色',
      type: 'Color',
    },
    {
      key: 'color',
      name: '文字颜色',
      type: 'Color',
    },
    {
      key: 'fontSize',
      name: '文字大小',
      type: 'Number',
    },
  ],
  initialData: {
    tabs: [
      {
        id: uuid(6),
        title: '华北',
        list: [
          {
            icon:
              '',
            goCity: '烟台',
            backCity: '北京',
            goDate: '08-18',
            goWeek: '周三',
            airline: '中国联合航空',
            price: 357,
            disCount: '4',
          },
        ],
      },
    ],
    layout: 'single',
    color: 'rgba(153,153,153,1)',
    activeColor: 'rgba(0,102,204,1)',
    fontSize: 16,
  },
};

When the component is initialized, the corresponding structure is agreed. When the component is dragged into the canvas area, we can get the currently selected component data, and then the property panel on the right can render the corresponding editable form items. Look at the code in the form area on the right:

const FormEditor = (props) => {
  const { formData, defaultValue } = props;
  console.log('FormEditor props', props);
  const [form] = Form.useForm();

  const handleFormChange = () => {
    console.log('表单更新',form.getFieldsValue());
  };

  return (
    <Form
      form={form}
      initialValues={defaultValue}
      onValuesChange={handleFormChange}
    >
      {formData.map((item, i) => {
        return (
          <React.Fragment key={i}>
            {item.type === 'Number' && (
              <Form.Item label={item.name} name={item.key}>
                <InputNumber max={item.range && item.range[1]} />
              </Form.Item>
            )}
            {item.type === 'Text' && (
              <Form.Item label={item.name} name={item.key}>
                <Input />
              </Form.Item>
            )}
            {item.type === 'TitleList' && (
              <Form.Item label={item.name} name={item.key}>
                <TitleList />
              </Form.Item>
            )}
            {item.type === 'Select' && (
              <Form.Item label={item.name} name={item.key}>
                <Select placeholder="请选择">
                  {item.options.map((v: any, i: number) => {
                    return (
                      <Option value={v.key} key={i}>
                        {v.text}
                      </Option>
                    );
                  })}
                </Select>
              </Form.Item>
            )}
          </React.Fragment>
        );
      })}
    </Form>
  );
};

onValuesChange will be triggered when the specific form item in the form area is changed, that is, the callback event will be triggered when the ant design form is updated. At this time the data will be updated to store . The data source of the canvas is store in componentData and the page will be updated in real time. Look at the overall data flow diagram:


At this point, the second problem is solved.

Then look at the third question: Can the canvas area and the rendering of the component during preview share a set of rendering logic?

Component sharing

We can understand the preview component as a static version or a snapshot version of the canvas area. From the perspective of page rendering, there is not much difference, so from the code design, the two parts can of course share a component. We call this shared component RenderComponent.tsx , the data source is store in componentData , and then combined with the DynamicComponent component, we get the following code:

const RenderComponent = memo((props) => {
  const {
    componentData,
  } = props;
  return (
    <>
      {componentData.map((value) => (
        <div
          key={value.id}
        >
          <DynamicComponent {...value} />
        </div>
      ))}
    </>
  );
});

Data storage/distribution

As for the fourth question: component data (consider adding components, deleting components, component rendering/preview and other scenarios), in fact, I have already mentioned it when answering the second question above. store is maintained globally:

state:{
  // 所有添加到画布中的组件数据
  componentData:[],
  // 当前编辑的组件数据
  curComponent: {}
}

reducers:{
  // 添加组件到componentData
  addComponentData(){},
  // 编辑组件,更新componentData及curComponent
  editComponentData(){},
  // 删除组件
  delComponentData(){}
}

For visual editor, there must be a global state management mechanism to store and distribute data. This is also very helpful for the sharing and synchronization of the data state.

Component development/maintenance

Look at the last question mentioned above: component library (consider scenarios where new components meet business needs).

There are currently two common practices for this:

  • Directly in the project
  • Extracted into npm package to form an independent third-party component library

If it is the early stage of the project, I feel that the first approach is not impossible, which is convenient for debugging. But in the long run, there will never be fewer components that are deposited in the marketing scenario. It is a wise choice to draw a third-party npm package. At the same time, it must cooperate with a management system similar to the component management backend to manage the components in a unified manner.

Back to the component itself, there must be strict development specifications. In principle, each component is only different in presentation, and the conventional component R&D specifications must be followed. As for how to restrict, you can do it through documentation (weak) or cli (strong).

template

In addition to the above questions, there is one more point that is not mentioned: templates. We know that marketing activities have a very typical feature: similar pages. If the operation/product classmates generate a page from scratch is also very time-consuming, and most of the activities belong to a certain category, we can draw these similar activities into templates. Creating based on templates will save a lot of time and effort. In view of the fact that this part of the content is still under development and migration, I won't elaborate on it for now.

At this point, I feel visual editor have been answered in the form of questions. In fact, both components dynamically loaded or component schema design, design data structure, maintenance component library, etc., each team can develop a set of their own norms, there is no absolute right or wrong.

In fact, in the implementation of this editor, there are many low-level implementation details that cannot be ignored. include:

  • Drag
  • Component layer hierarchy
  • Zoom in/out
  • Undo/redo
  • Adsorption
  • Bound event/animation

I won’t go into these details one by one. I recommend an article: Visual Drag-and-Drop Component Library Some Technical Points Principle Analysis . The article has a very detailed description of the technical points mentioned above.

low code/no code/pro code

Having said so much above, let us return to the low code/no code/pro code mentioned at the beginning of the article. I will elaborate on these three in conjunction with our visual editor.

First, let's look at the general process of operation/development students using the editor to create activities:

no code

First, let’s briefly explain what no code : literally it means no code, that is, no code is written.

From the above flowchart, you can see that operation/product students can build a fully functional activity page through the visual editor without writing a line of code. This corresponding is no code .

low code

low code is low code and write less code.

In the above flow chart, it is more reflected in the front-end student development component library. Part of the code needs to be written, and the whole is generated by dragging and dropping. The corresponding is low code .

pro code

pro code is pure code, that is, it does not use any visualization tools, but depends on the development of handwritten code. Before low code and no code appeared, this method was the most common research and development method.

In the above flowchart, this part is not reflected. But in actual business development, such scenarios often exist. Maybe a current marketing campaign has complex interactions and long links, so it is difficult to customize it through a visual editor like this article. Only through development to manually write code to meet business needs.

The visual editor is more to meet page development with similar rules, and the primary responsibility is to reduce the development of repetitive business

Outlook

At this point, I have roughly sorted out the process of building and exploring the evolution of a marketing system.

But this is just the beginning. This article focuses more on the exploration of the front-end side, and it is only the first step towards a visual editor. It is just a project that is more inclined to a pure front-end, and a lot of logic has not been considered. Here is a list of what to do later:

  • Template market
  • data center
  • Buried point
  • Component debugging/preview
  • Cache
  • Open api capability
  • CDN
  • Cross-terminal
  • ...

❤️ Three Loves

1. If you think this article is not bad, come to share, like, and watch three consecutive, so that more people can see it~

2. Follow the public front-end forest , and regularly push you fresh dry goods and good articles.

3. At special stages, wear a mask and do personal protection.

阅读 3.5k

前端森林公众号
一个有温度的前端号,关注行业前沿。从基础到架构,携手你我共同成长。
2.3k 声望
13.2k 粉丝
0 条评论
2.3k 声望
13.2k 粉丝
文章目录
宣传栏