📢 I am nothing but a vegetable

Some time ago, the team decided to build a cross-project and cross-business UI component library. The reason is that our department has more and more products, and each product is designed to multiple ends (such as Web/Mobile/PC/Android, etc.). In order to respond quickly, we decided to build a unified and visual UI component library with departmental characteristics.

All of the component styles and interactions were laid out in vision, and we went through rounds of review and discussion within the front end group, and eventually everyone developed several components. As for me, THERE are several components, some are a little simpler, some have complex interaction and state, this article is mainly to record my first time to develop a common component thinking ~

The components I am responsible for are: Skeleton placeholder component, Card component, Button Button component and grid component

Preparatory work

This is the first time to develop a common component. Before, it was mainly in the project to remove some simple reusable logic business components. For example, for the Button component, FOR me, I was more likely to consider some common states, such as the previous Button component code is like this:

/** * @extends {React.Component} * @property {string} text - property {string} size - Button size, Small /middle/big * @property {string} icon - Button icon, empty if not needed * @property {string} color - type, Orange /ghost/white * @property {object} style - style * @property {string} textSize - button textSize, Small /middle/big/super * @property {Boolean} disabled * @property {string} iconSeat Left /right * @property {function} onHandleClick - click event * @property {Boolean} isLock - Lock click If locks are required, make sure all operations are synchronous or all asynchronous actions are completed before return) */
Copy the code

This is a Button component that I pulled out of the business content. It has a bit of a common component look, but it’s not enough. Therefore, BEFORE developing common components this time, I deliberately made adequate preparations.

Componentized development

What is componentization? This problem I believe most front-end engineers know ~ when I installed X with my primary school younger brothers and sisters, they asked me, what is the component, I smiled and did not speak, threw out the www.baidu.com website, told them, look up…

Componentization refers to the process in which multiple functional modules are split and reassembled when a complex system is decoupled. Various attributes and states reflect its internal characteristics.

To put it simply, we can think of a page as a transformer, made up of different parts, such as Header parts, Hand parts, Footer parts, etc…

Then, when we want to make a Transformer, we can do a product very quickly by just using the parts

Design principles

I believe that you do not want to listen to my force, directly into the theme, I want to design a common component, how to design, I searched a lot of related articles on the Internet, such as:

After I read some articles and compiled some other people’s opinions on component design (links will be posted at the bottom), first of all, we need to have a component-based design mindset. What is it good for? It helps us develop efficiently

The official documentation

This document must be detailed, otherwise others will look at it. At the same time, each component should be expressed as much as possible, the origin of this component, use scenario, how to design, API, parameter transfer, etc

👉 Those interested can check out ant Design’s documentation, which includes documentation for each component on Github in addition to usage documentation

Code review

There should be a place for developers to debug code in real time so that users of other components can better understand the props

Using the instance

Provides some example code on how to import their data into the UI to make it easier for other developers to get started with their usage.

How to design

  1. standard
  2. independence
  3. Reuse and ease of use
  4. Acyclic dependence principle (ADP)
  5. The entry checks the validity of the parameters and the exit checks the correctness of the returns
  6. Stable Abstraction Principle (SAP)
  7. .

How to design above I frankly, from 👉 to talk about component design to write, too lazy to write ~(respect the author, respect the original, we directly go to see his article ha ~)

Set out to develop

The component library in our group was developed based on Ant Design. Well, AT first I thought antD was already installed in the project. However, when I checked package.json, I found that antD was not installed. The idea was to take a look at Ant Design code and take a look at it, remove the internationalization and some of the different differences, and add your own department’s unique interactions and styles

Aoli force to, this what ah, what trifle, went to see the source code directly??

So, I chose the simplest Card component and studied a wave of WC. I was surprised when I saw it. Turns out I’m still too bad…

This card component, if I didn’t look at the source before, I guess it looks like this:

/** * @class Card * @extends {React.Component} * @property {string} title - Title * @Property {string} content - Content * @property {string} size - Card size * @property {string} extra - upper right extra * @property {object} style - Style * @property {function} onClick - Click event */
Copy the code

If the user wants to change the style of the content, it will be easy to open a contentStyle for him

Content

= content

= typeof Content > = Array

What if the user passes a ReactNode, like this

const loadingNode = (
  <div>loading</div>
)

<Card content={loadingNode} />
Copy the code

Or maybe the user wants to

const loadingNode = '

I am loading

'
; <Card content={loadingNode} />; Copy the code

What users really want is for you to escape through dangerouslySetInnerHTML, not for you to display the content directly.

Forget it, go to see the source code directly ~

Look at the source of pain

At first glance, what is this config-provider? SizeContext (@xxx) : SizeContext (@xxx) : SizeContext (@xxx) : SizeContext (@xxx) : SizeContext

When I read React Practice: Design Patterns and Best Practices, I realized what config-Provider and ConfigConsumer are. Ant Design 🐂 B!!

👉 if you are interested in the poke here is the source code: Ant Design-card

To my own developmentCardComponent for example ~

Let’s take a look at what my Card component does…

attribute

parameter instructions type The default value
size The card size string middle
style Card style object
loading Loading can be used to display a placeholder while the card content is still loading boolean true
isShadow Whether the card has a shadow boolean true
title The title card string|ReactNode
headStyle Custom header area styles object
headWrapName Custom title area className string ${prefixCls}-card-head
extra The operation area in the upper right corner of the card string|ReactNode
onClick Card click event () => void

So naturally, those are the Props

exportinterface AbstractCardProps { size? : string; style? : React.CSSProperties; loading? :Boolean; isShadow? :Boolean; title? : string | React.ReactNode; headStyle? : React.CSSProperties; headWrapName? : string; extra? : string | React.ReactNode; onClick? :(a)= > void;
}
Copy the code

We can then import {ConfigConsumer, ConfigConsumerProps} from ‘.. /config-provider’ /config-provider’ /config-provider’ /config-provider’ /config-provider

We then deal with some props

// Get a prefix, such as antd-, like ant-design, for all classes
const prefixCls = getPrefixCls('card', customizePrefixCls);

// Define the header
let head: React.ReactNode;

// Define the loading state
let loadingBlock: React.ReactNode;

if (title || extra) {
  head = (
    <div
      style={headStyle}
      className={` ${prefixCls}-headThe ${headWrapName && headWrapName} `} >
      <div className={` ${prefixCls}-head-wrapper`} >
        {title && <div className={` ${prefixCls}-head-title`} >{title}</div>}
        {extra && <div className={` ${prefixCls}-extra`} >{extra}</div>}
      </div>
    </div>
  );
}

const body = (
  <div className={` ${prefixCls}-body`} >{loading ? loadingBlock : children}</div>
);
Copy the code

Before we export, we pack through the SizeContext higher-order components

< sizecontext. Consumer> {size => {// If you have a custom size, use yours. Not with the default size in SizeContext const mergedSize = customizeSize | | size; // Handle all classNames const classString = classNames(prefixCls, className, {[' ${prefixCls}-loading ']: loading, [`${prefixCls}-shadow`]: isShadow, [`${prefixCls}-${mergedSize}`]: mergedSize }); return ( <div className={classString} style={style} onClick={onClick && onClick}> {head} {body} </div> ); }} </SizeContext.Consumer>Copy the code

For styles, instead of just writing some color or font size in the less file, for Ant-Design, they have a style file with a lot of defined variables in it, and even a theme file, so if you want to customize the theme, Just need to say a copy of the theme file, and then modify, you can directly complete the custom theme requirements ~

How to say, in fact, after removing some complex requirements out, the relative Card component is much simpler, we look at a few more components, we will find, really sweet, the original component can also be designed in this way, compared to my previous design of those low B components, this component looks much higher. 🙃

subsequent

Looking back, this article is a bit like writing notes, not what dry goods, but the main purpose or want to pass to everyone an idea: is to have time, you can consider to see some excellent components of the source ~ Aoli force to!

📢 update, this is the postscript, front-end muck I dare not say I will write Button components, this is my development of Button components encountered problems and thinking, I hope you have some use ~

The current progress

The current progress of the group is also in order. After all, everyone agrees with this project, and v1 version is relatively loose. The basic version should be released first, and then details and optimization should be explored deeply


A link to the

  • Talk about component design
  • Zhihu – Some thoughts on the componentization of front-end UI
  • React Component design pattern basics
  • Hiro’s blog