One, foreword

Last week, I wrote my year-end review for 2021. In 2021, I did almost 30 functional iterations, not including the daily need for temporary fixes or online bug maintenance, an average of 2.5 iterations a month. More than half of this is business function development.

What is business function development? This is how I understand it. Taking the process of selling goods as an example, to realize the whole process, there needs to be a front-end sales page, a complete purchase process flow page, a purchase success page, a backstage sales goods management page, an order management page, etc. Business function development requires developers to understand what to do and how to do it. If the developer is not familiar with the business, it may be the case that the user wants to buy product A, only to find out after paying for product B.

Most of the time, we get business requests for improvements or enhancements to existing features, which can be done without too much developer time. For example, in my recent requirement, I removed a dozen small modification points, which basically enhanced the functions on the original basis, such as adding a button to filter the list page according to a certain rule, or taking out some items in the original added form and putting them into a new form for maintenance. These requirements are not hard to implement, and if I just implement the features without thinking about them, my development skills will probably stay stagnant and my mindset will stay fixed.

Both b-side business and C-side business, technology needs to better serve the users of the product, that is, our users. Business and technology development are closely related, and pure functional development can no longer meet the growing and enhanced functional requirements.

As summarized in my PPT, WHEN I was thinking about how to develop “enabling” businesses, the first thing that came to mind was the building of business components.

Second, business component understanding

2.1 What is a Business component

Front-end component-based development, we will separate part of the function, the data layer, view layer, control layer of this part of the function are all encapsulated in a component, only exposed some parameters and methods, so as to achieve the separate maintenance and reuse of this part of the function.

A business component is a component that separates some functions strongly related to business logic and maintains them separately. Strong relevance to business logic means that it will not be applicable to all requirements development, but as business capabilities grow, we will be able to find certain stars in the sea of stars with synchronized flash frequencies and maintain and manage them individually.

2.2 Why Encapsulate Business Components

As mentioned earlier, as business functions continue to grow, there will be more and more code in our projects, and the code logic will become complex. We encapsulate business components because:

1) Complex functions can be disassembled for subsequent rapid iteration;

2) Solve the problem of cross-project reuse, reduce duplicate code and repeated development;

3) Unified code quality, can ensure the quality of code in rapid development.

2.3 How to Determine whether a Service Function can be Encapsulated as a Service component

The definition mainly depends on the following points:

1) Similar page presentation and interaction;

2) Use similar data;

3) Consistent processing process;

4) Similar business goals.

2.4 Differences between Business Components and base components

Let me illustrate it a little bit better. For example, we have encapsulated the list component. No matter what kind of business needs, if a new paginated list page is needed, the list component can be used for rapid development basically. This has nothing to do with specific business functions and can be regarded as a basic component. However, if it is a remarks function, only some service functions are required, and these service functions belong to different pages, such as order management list page and product management list page. The page interaction and interface are the same, and the interface input parameters may be different. The remarks popup can be encapsulated as a service component.

Implementation of business components

Our project is based on React+Antd, so the UI components are directly provided by Antd, written mainly in JSX+Hooks syntax.

3.1 Project Structure

Our project is basically the following structure, including interface, business component, basic component, constant, CSS module, business module, tool class and other parts, such a structure is convenient for development and maintenance. Based on the understanding and thinking of the business, we will encapsulate some business components and business tool classes according to the actual situation. As a result of this work, I was able to save a lot of development time in most iterations, and the development quality was very high (the beta phase and online bugs were significantly reduced).

3.2 Data editing/view component implementation

3.2.1 UI

Data view

Data upload

3.2.2 Component Encapsulation

According to the above UI, it is not difficult to see that the main differences between data view and data upload pop-ups are the title of the popover, the content of the popover, whether it can be operated and the button at the bottom of the popover. So I did the following:

1) Component communication: parent-child communication. The parent component passes parameters to the child component through props. The main parameters are visible-whether the popup is displayed, data-operation data, onCancel- callback function to cancel the operation, and type verification of parameters using the validator provided by PropTypes. Child components communicate with parent components via the callback function -oncancel;

2) Distinguish popover types: modalType variable is set to distinguish popover types, enumeration values are: View: data view, edit: data upload;

3) Distinguish pop-up contents, operations, bottom buttons and other differences: Set the commodity object :productObj, used to distinguish different contents, operations, bottom buttons;

4) Upload component: We have encapsulated the upload component twice, which can be used together with antD’s From component;

/ * * *@description Commodity business - Information editing/view */
import React, { useRef, useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Form, Modal, Input, Button, Space } from 'antd';
import { ExclamationCircleFilled } from '@ant-design/icons';
import { Upload } from '@/components';

const ProductMaterial = ({ visible, data, onCancel }) = > {
  const formRef = useRef({});
  const layout = {
    labelCol: { span: 4 },
    wrapperCol: { span: 20}};const [confirmLoading, setConfirmLoading] = useState(false);
  const [productItem, setProductItem] = useState({});

  /** * operation - close the popbox *@param {string} Type Key value of the subrack to be closed *@param {boolean} Refresh Whether to refresh the list after the popover closes@return {void} No * /
  const handleCancel = refresh= > {
    setConfirmLoading(false);
    setProductItem({});
    onCancel && onCancel(refresh);
  };

  /** * operation - confirm button *@param {void} No *@return {void} No * /
  const handleOk = () = > {
    formRef.current.submit();
  };

  / * *@name Commodity object */
  const productObj = {
    edit: {
      modalTitle: 'Data upload'.// Popup to display the title
      productLabel: 'Detail Document'.// Specify the label value
      endorseLabel: 'Annotated document'.// Annotate the value of the item label
      footer: (
        <>
          <Button onClick={()= >> cancel handleCancel (false)}</Button>
          <Button type="primary" onClick={handleOk}>determine</Button>
        </>
      ), // Bottom button group
    },
    view: {
      modalTitle: 'Data Viewing'.productLabel: 'View details'.endorseLabel: 'Comment view'.footer: <Button onClick={()= >HandleCancel (false)} > shut down</Button>,}}; useEffect(() = > {
    if (data.modalType) {
      let productItemInit = productObj[data.modalType];
      productItemInit.editFlag = data.modalType === 'edit' ? true : false; // Whether a Boolean value can be edited
      setProductItem(productItemInit);
    }
  }, [visible]);

  /** * operation - upload *@param {string} Type Upload image type *@return {void} No * /
  const uploadCallback = type= > {
    return url= > {
      formRef.current.setFieldsValue({
        [type]: url,
      });
    };
  };

  /** * operation - submit *@param {Object} Value Form data object *@return {void} No * /
  const handleSubmit = value= > {
    // The request interface submits the form data, and the result is called back to the parent component after the request succeeds
    onCancel && onCancel(true);
  };

  return (
    <Modal title={productItem.modalTitle} width={800} visible={visible} confirmLoading={confirmLoading} footer={productItem.footer} onCancel={()= > handleCancel(false)}>
      <Form {. layout} labelAlign="left" onFinish={handleSubmit} ref={formRef}>
        {productItem.editFlag ? (
          <Space style={{ marginBottom: '15px' }}>
            <ExclamationCircleFilled style={{ color: '#d80000', fontSize: '16px' }} />You can upload files in any format</Space>
        ) : null}
        <Form.Item label={productItem.productLabel} name="productFileUrl" rules={[{ required: true.message:'Please upload ${productItem.productLabel}} > `}]
          <Upload callback={uploadCallback('productFileUrl')} accept="*" limit={Infinity} disabled={! productItem.editFlag} isArray="true" />
        </Form.Item>
        <Form.Item label={productItem.endorseLabel} name="endorseFileUrl">
          <Upload callback={uploadCallback('endorseFileUrl')} accept="*" limit={Infinity} disabled={! productItem.editFlag} isArray="true" />
        </Form.Item>
        <Form.Item label="Other Information" name="otherFileUrl">
          <Upload callback={uploadCallback('otherFileUrl')} accept="*" limit={Infinity} disabled={! productItem.editFlag} isArray="true" />
        </Form.Item>
        <Form.Item name="remark" label="Modify remarks">
          <Input.TextArea maxLength={1000} rows={3} placeholder="Please fill in the modification notes" disabled={! productItem.editFlag} />
        </Form.Item>
      </Form>
    </Modal>
  );
};

ProductMaterial.propTypes = {
  visible: PropTypes.bool.isRequired, // Popover close control variables must be passed
  data: PropTypes.object.isRequired, // The component input parameter must be passed
  onCancel: PropTypes.func, // Popover close event
};

ProductMaterial.defaultProps = {
  visible: false.data: {}};export default ProductMaterial;
Copy the code

3.2.3 Importing Components

Usage is basically consistent with common base components

1) Introduce the ProductMaterial component and place it in the view layer on the page that needs to display data pop-ups;

2) Since it is a list operation, operation items are added to the table array, and operation buttons are placed inside the operation items. I put view and upload together, and these two buttons will be placed in different columns of the table in normal requirements;

3) Add operation functions to control the opening and closing of pop-ups and the callback after uploading

/ * * *@description Merchandise Management - Home page */
import React, { useState, useRef } from 'react';
import { Button } from 'antd';
import { List } from '@/components';
import { PRODUCT_COLUMNS, PRODUCT_FIELDS } from '@/constants/product';
import { list } from '@/api/product';
// Business component import
import { ProductMaterial } from '@/bundleComponents';

const ProductList = () = > {
  const listRef = useRef();
  let columns = _.cloneDeep(PRODUCT_COLUMNS);
  const [visible, setVisible] = useState(false);
  const [recordData, setRecordData] = useState(false);

  /** * operation *@param {boolean} VisibleType Whether the popover displays a Boolean value *@param {Object} Data Data object *@param {boolean} Refresh Whether the list refreshes a Boolean value *@return {void} No * /
  const operate = (visibleType, data = {}, refresh) = > {
    setVisible(visibleType);
    setRecordData(data);
    // =>true: Refreshes the list
    if (refresh) {
      // Refresh the list}}; columns = columns.concat([ {title: 'operation'.width: 200.fixed: 'right'.// eslint-disable-next-line
      render: (text, record) = > (
        <>{/* View the operation */}<Button
            onClick={()= >{ operate(true, { ... record, modalType: 'view' }); }} > Data view</Button>{/* Upload operation */}<Button
            type="primary"
            onClick={()= >{ operate(true, { ... record, modalType: 'edit' }); }} style={{marginLeft: '10px'}} > Upload data</Button>
        </>),},]);return (
    <div>
      <List fields={PRODUCT_FIELDS} columns={columns} http={list} ref={listRef} />{/* Business components use */}<ProductMaterial visible={visible} data={recordData} onCancel={refresh= > operate(false, {}, refresh)} />
    </div>
  );
};

export default ProductList;
Copy the code

How do the big boys think about business components

From starting business components to developing a business component library for your own projects, the development ideas and the final summary are well written and worth reading.

  • 1.2 w word | from 0 to 1 to fit Web Components business component library development
  • Three key points of implementation of front-end business component library technology

Five, the summary

In large and repeat business needs, refine search, you can split the function module, even seemingly ordinary or habit of function, also can find window, the window can not only improve the developer’s technical ability, and can improve the quality of development, and can help developers to jump out of the box, is fully staffed.

When meeting new requirements, we can jump out of the mindset of blindly copy-and-paste development and properly think about how to design our own functional modules, so that we can complete the iterative tasks with higher quality and efficiency.

There is a light north wind in winter and today is a fine day.