PrefaceMany friends will encounter many problems like me when they try to encapsulate components for the first time. For example, other people’s components have color attributes. When we use the component, we pass in the attribute value described in the component document, such as primary. Then the font color of this component will become the color corresponding to primary. How is this done? Also, the component class names encapsulated by others have their own unique prefixes. How do you deal with this? Do you have to add prefixes to all CSS class names? This is too troublesome! If you are confused about these questions, you can read this article. I will refer to antd's divider component to explain how to encapsulate a component based on React, and answer some of the above questions. Please read it patiently! How does antd encapsulate components?Warehouse Address
Divider component source codeThe source code of antd uses TypeScript syntax, so students who don't understand the syntax should learn it in time! import * as React from 'react'; import classNames from 'classnames'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; export interface DividerProps { prefixCls?: string; type?: 'horizontal' | 'vertical'; orientation?: 'left' | 'right' | 'center'; className?: string; children?: React.ReactNode; dashed?: boolean; style?: React.CSSProperties; plain?: boolean; } const Divider: React.FC<DividerProps> = props => ( <ConfigConsumer> {({ getPrefixCls, direction }: ConfigConsumerProps) => { const { prefixCls: customizePrefixCls, type = 'horizontal', orientation = 'center', className, children, dashed, plain, ...restProps } = props; const prefixCls = getPrefixCls('divider', customizePrefixCls); const orientationPrefix = orientation.length > 0 ? `-${orientation}` : orientation; const hasChildren = !!children; const classString = classNames( prefixCls, `${prefixCls}-${type}`, { [`${prefixCls}-with-text`]: hasChildren, [`${prefixCls}-with-text${orientationPrefix}`]: hasChildren, [`${prefixCls}-dashed`]: !!dashed, [`${prefixCls}-plain`]: !!plain, [`${prefixCls}-rtl`]: direction === 'rtl', }, className, ); return ( <div className={classString} {...restProps} role="separator"> {children && <span className={`${prefixCls}-inner-text`}>{children}</span>} </div> ); }} </ConfigConsumer> ); export default Divider; How to expose component properties In the source code, the first thing you see is the following content. These properties are also the properties exposed by the divider component. We can pass in the type attribute like export interface DividerProps { // interface is TypeScript syntax prefixCls?: string; type?: 'horizontal' | 'vertical'; // Limit type to only one of the two values orientation?: 'left' | 'right' | 'center'; className?: string; children?: React.ReactNode; dashed?: boolean; style?: React.CSSProperties; plain?: boolean; } In the above attributes, we also found that className and style are relatively common attributes, which means we can use these attributes like How to set a unified class name prefix We know that antd's component class names have their own unique prefix <ConfigConsumer> {({ getPrefixCls, direction }: ConfigConsumerProps) => { const { prefixCls: customizePrefixCls, type = 'horizontal', orientation = 'center', className, children, dashed, plain, ...restProps } = props; const prefixCls = getPrefixCls('divider', customizePrefixCls); From the source code, we find prefixCls, which is generated by the getPrefixCls method. Let's take a look at the source code of the getPrefixCls method, as follows. export interface ConfigConsumerProps { ... getPrefixCls: (suffixCls?: string, customizePrefixCls?: string) => string; ... } const defaultGetPrefixCls = (suffixCls?: string, customizePrefixCls?: string) => { if (customizePrefixCls) return customizePrefixCls; return suffixCls ? `ant-${suffixCls}` : 'ant'; }; It is not difficult to find that the class name prefix generated at this time is How to handle styles and class namesThe components we encapsulate must have preset styles. Because the styles are defined by class names, and the attribute values we pass in will determine which class name to add to the component, how is this achieved? Let’s look at the source code below. import classNames from 'classnames'; const classString = classNames( prefixCls, `${prefixCls}-${type}`, { [`${prefixCls}-with-text`]: hasChildren, [`${prefixCls}-with-text${orientationPrefix}`]: hasChildren, [`${prefixCls}-dashed`]: !!dashed, [`${prefixCls}-plain`]: !!plain, [`${prefixCls}-rtl`]: direction === 'rtl', }, className, ); return ( <div className={classString} {...restProps} role="separator"> {children && <span className={`${prefixCls}-inner-text`}>{children}</span>} </div> ); We found that it defines a constant of all class names through the classNames method (classNames is a component of React that handles multiple class names), and then passes it to the className attribute in the div. In fact, the generated class name is Finally, let’s take a look at how its CSS style code is written! Divider component style source codeThe styles of antd components are written in Less. Students who are not familiar with Less syntax must learn about it. @import '../../style/themes/index'; @import '../../style/mixins/index'; @divider-prefix-cls: ~'@{ant-prefix}-divider'; // You can see that this corresponds to the class name prefix mentioned earlier.@{divider-prefix-cls} { .reset-component(); border-top: @border-width-base solid @divider-color; &-vertical { // The full class name here is actually ant-divider-vertical, which is the style corresponding to the divider component when the type attribute value is vertical position: relative; top: -0.06em; display: inline-block; height: 0.9em; margin: 0 8px; vertical-align: middle; border-top: 0; border-left: @border-width-base solid @divider-color; } &-horizontal { display: flex; clear: both; width: 100%; min-width: 100%; margin: 24px 0; } &-horizontal&-with-text { display: flex; margin: 16px 0; color: @heading-color; font-weight: 500; font-size: @font-size-lg; white-space: nowrap; text-align: center; border-top: 0; border-top-color: @divider-color; &::before, &::after { position: relative; top: 50%; width: 50%; border-top: @border-width-base solid transparent; // Chrome does not accept `inherit` in `border-top` border-top-color: inherit; border-bottom: 0; transform: translateY(50%); content: ''; } } &-horizontal&-with-text-left { &::before { top: 50%; width: @divider-orientation-margin; } &::after { top: 50%; width: 100% - @divider-orientation-margin; } } &-horizontal&-with-text-right { &::before { top: 50%; width: 100% - @divider-orientation-margin; } &::after { top: 50%; width: @divider-orientation-margin; } } &-inner-text { display: inline-block; padding: 0 @divider-text-padding; } &-dashed { background: none; border-color: @divider-color; border-style: dashed; border-width: @border-width-base 0 0; } &-horizontal&-with-text&-dashed { border-top: 0; &::before, &::after { border-style: dashed none none; } } &-vertical&-dashed { border-width: 0 0 0 @border-width-base; } &-plain&-with-text { color: @text-color; font-weight: normal; font-size: @font-size-base; } } @import './rtl'; In this way, I believe that students also have a general understanding of how to encapsulate a component and the key points. There are still many places in the source code worth learning, such as the definition and use of ConfigConsumer here. Students who are interested are welcome to communicate together. This is the end of this article about the implementation steps of React-based encapsulated components. For more relevant React encapsulated component content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: How to use HTML+CSS to create TG-vision homepage
>>: SQL insert into statement writing method explanation
Table of contents 1 Node.js method of sending ema...
Download Download address: https://dev.mysql.com/...
Table of contents Preface Introduction ngram full...
MySQL supports nested transactions, but not many ...
I. Introduction 1: SSL Certificate My domain name...
Simple example of HTML checkbox and radio style b...
HTML reuse is a term that is rarely mentioned. Tod...
This article shares the specific code of js to im...
Editor: This article discusses the role that inte...
This article uses examples to explain the knowled...
<br />This article will briefly introduce yo...
<META http-equiv="Page-Enter" CONTENT...
Last time, we came up with two header layouts, on...
Why learn vim Linux has a large number of configu...
1. HTML Overview 1.HTML: Hypertext Markup Languag...