Новое понимание фронтенд-шлаковой разработки общедоступных компонентов пользовательского интерфейса

React.js

📢 Я всего лишь овощи

Некоторое время назад группа решила создать кросс-проектную и кросс-бизнес библиотеку компонентов пользовательского интерфейса, потому что у нашего отдела появляется все больше и больше продуктов, и каждый продукт предназначен для нескольких терминалов (таких как Web/Mobile/PC/Android и т. д.). .) В ответ на поставленную цель было принято решение сделать унифицированную и наглядную библиотеку UI-компонентов с ведомственными характеристиками.

Visual дал все стили компонентов и эффекты взаимодействия, а наша фронтенд-группа также прошла раунды обзора и обсуждения, и, наконец, все разделились на несколько компонентов для разработки. Что касается меня, я также разделил на несколько компонентов, некоторые немного проще, некоторые имеют сложные взаимодействия и состояния, эта статья в основном для того, чтобы записать себяпервый разДумаю о разработке публичного компонента~

Компоненты, за которые я отвечаю: компонент заполнителя скелета скелета, компонент карты, компонент кнопки, компонент сетки.

первоначальная подготовительная работа

Это первый опыт разработки публичных компонентов.Раньше это было в основном в проекте, и были извлечены некоторые бизнес-компоненты с простой логикой повторного использования.Например дляButtonКомпоненты, для меня то, что я, возможно, рассматривал раньше, это просто некоторые часто используемые состояния, такие как предыдущееButtonКод компонента такой:

/**
 * @class Button
 * @extends {React.Component}
 * @property {string} text - 按钮文本
 * @property {string} size - 按钮大小,small/middle/big
 * @property {string} icon - 按钮携带的icon,不需要则为空
 * @property {string} color - 类型,可选值为 orange/ghost/white
 * @property {object} style - 样式
 * @property {string} textSize - 按钮文案文字大小,small/middle/big/super
 * @property {boolean} disabled - 可否点击
 * @property {string} iconSeat - 按钮icon的位置,left/right
 * @property {function} onHandleClick - 点击事件
 * @property {boolean} isLock - 是否锁定点击(注:如果需要使用锁,请保证所有操作为同步或者所有的异步行为执行完再return)
 */

Это то, что я извлек из бизнес-контента.ButtonКомпоненты, есть след общих компонентов, но на самом деле этого далеко не достаточно. Поэтому, прежде чем разрабатывать публичные компоненты в этот раз, я сознательно сделал соответствующие приготовления.

разработка компонента

Что такое компонентизация? Я полагаю, что большинство интерфейсных инженеров знают этот вопрос~ Когда я устанавливал X со своими братьями и сестрами из начальной школы, они спросили меня, что такое компонент, я засмеялся, не говоря ни слова, и выбросил его.www.baidu.comURL, скажи им, проверь сам...

Компонентизация относится к процессу разделения и реорганизации нескольких функциональных модулей при разделении сложных систем.Существуют различные атрибуты и состояния, отражающие их внутренние характеристики.

Проще говоря, мы можем думать о страницах как о трансформерах, которые состоят из разных частей, таких какHeader零件,Hand零件,Footer零件Ждать...

Затем, когда мы захотим сделать трансформер, мы сможем напрямую использовать эти детали и быстро сделать продукт~

Принципы дизайна

Я считаю, что вы не хотите слушать меня и перейти непосредственно к теме. Я хочу спроектировать компонент, который каждый может использовать универсально. Как мне его спроектировать? Я искал много связанных статей в Интернете, таких как:

После того, как я прочитал несколько статей, я разобрался с некоторыми взглядами других людей на компонентный дизайн (партнерские ссылки будут размещены внизу), прежде всего, у нас должен быть набор мышления компонентного дизайна, какая от него польза? Это может помочь нам эффективно развиваться~

официальная документация

Этот документ должен быть подробным, иначе увидит других. В то же время каждый компонент должен быть максимально выражен, происхождение компонента, сценарии использования, как проектировать, API, передачу параметра и т. Д.

👉 Если вам интересно, вы можете ознакомиться с документацией по дизайну муравьев.Помимо документации по использованию, на github также есть документация по каждому компоненту.

чтение кода

Это должно предоставить место, где разработчики могут отлаживать код в режиме реального времени, чтобы пользователи этих других компонентов могли лучше понять каждый реквизит.Я считаю, что более популярные и популярные библиотеки пользовательского интерфейса имеют такой вид работы~

Пример использования

Предоставляет пример кода о том, как импортировать свои данные в пользовательский интерфейс, чтобы другие разработчики могли быстрее приступить к работе со своими вариантами использования.

как спроектировать

  1. стандартный
  2. независимость
  3. Повторное использование и простота использования
  4. Принцип ациклической зависимости (ADP)
  5. Проверить правильность параметров на входе, и проверить корректность возврата на выходе
  6. Принцип стабильной абстракции (SAP)
  7. ......

верх如何设计Признаюсь, от 👉Разговор о дизайне компонентовЭто я написал, мне лень писать~ (Респект автору, уважайте оригинальность, каждый может сразу перейти к его статье~)

начать разработку

Библиотека компонентов в нашей группе основана наAnt Designразработка, ну я думал она уже есть в проекте сначалаnpm install antdтеперь, кто знает, когда я пойду посмотретьpackage.jsonКогда я узнал, что это не работает, я спросил однокурсников C, которые отвечали за эту библиотеку компонентов, оказалось... Я хотел, чтобы мы посмотрели код Ant Design, а затем извлекли из него уроки, удалили интернационализация и некоторые другие различия.Предметы, а затем добавьте взаимодействие и стиль характеристик вашего собственного отдела~

奥力给,这啥啊,什么玩意啊,就直接去看源码了 ? ? ?

Так что выбрал самую простую КАРТОВУЮ составляющую, изучил волну, WC, не знаю, смотрел... Я был еще слишком тарелкой...

Этот компонент карты, если я не читал исходный код, думаю, он такой:

/**
 * @class Card
 * @extends {React.Component}
 * @property {string} title - 标题
 * @property {string} content - 内容
 * @property {string} size - 卡片大小
 * @property {string} extra - 右上角extra
 * @property {object} style - 样式
 * @property {function} onClick - 点击事件
 */

В этом направлении мысли пройдите весь путь и обнаружите, что если вы пройдетеcontentЭто точно не правильно, зачем, если пользователь хочет изменить стиль этой копии, то все просто, дай ему копиюcontentStyleВсе в порядке~

Так что же делать пользователю, если он хочет перенести строку?content<String>изменить его наcontent<Array>Ну, судитеtypeof content, если это массив, пройтись по тексту рендеринга~

Если пользователь загружаетReactNodeтипа вот так

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

<Card content={loadingNode} />

Или пользователь хочет этого~

const loadingNode = `<p className="loading">我是loading</p>`;

<Card content={loadingNode} />;

Чего на самом деле хотят пользователи, так это того, чтобы выdangerouslySetInnerHTMLИзбегайте его вместо того, чтобы отображать содержимое напрямую.

Забудьте об этом, просто посмотрите на исходный код~

Боль от просмотра исходного кода

Первый взгляд, что, этоconfig-providerЧто это такое? этоSizeContextЧто это такое, для чего используется этот файл less?@xxxАх, почему так много переменных, введенных файлом, все внешние.

когда я пошел посмотретьРеакция в действии: шаблоны проектирования и лучшие практикиПосле этой брошюры я пришел к этомуconfig-provider,ConfigConsumerЧто это такое. , а затем, прочитав полный компонент, я обнаружил, что Ant Design 🐂 B ! ! !

👉 Если вам интересно, нажмите здесь, чтобы увидеть исходный код:Ant Design-Card

разработал самCardКомпоненты, например~

Давайте посмотрим на функции моего компонента Card...

Атрибуты

параметр иллюстрировать Типы По умолчанию
size размер карты string middle
style Стиль карты object -
loading Когда содержимое карты все еще загружается, вы можете использовать загрузку для отображения заполнителя. boolean true
isShadow Есть ли у карты тени boolean true
title название карты string|ReactNode -
headStyle Пользовательский стиль области заголовка object -
headWrapName Настраиваемая область заголовка className string ${prefixCls}-card-head
extra Зона действия в правом верхнем углу карты string|ReactNode -
onClick клик по карте () => void -

Так что, естественно, наш реквизит - это такие вещи~

export interface AbstractCardProps {
  size?: string;
  style?: React.CSSProperties;
  loading?: Boolean;
  isShadow?: Boolean;
  title?: string | React.ReactNode;
  headStyle?: React.CSSProperties;
  headWrapName?: string;
  extra?: string | React.ReactNode;
  onClick?: () => void;
}

Затем мы вводимimport { ConfigConsumer, ConfigConsumerProps } from '../config-provider'обрабатывать,Не спрашивайте,просто вы пока в этом не разбираетесь.Короче говоря,это бредовая работа высокоуровневых компонентов.Если вам интересно,можете сходить посмотреть.Вот это действительно интересно.👉config-provider

Давайте продолжим с реквизитом~

// 获取前缀,比如像ant-design一样,所有的class都是以 antd- 开头
const prefixCls = getPrefixCls('card', customizePrefixCls);

// 定义头部
let head: React.ReactNode;

// 定义加载时的状态
let loadingBlock: React.ReactNode;

if (title || extra) {
  head = (
    <div
      style={headStyle}
      className={`${prefixCls}-head ${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>
);

Прежде чем экспортировать, мы передаемSizeContextУпаковка высокоуровневых компонентов

<SizeContext.Consumer>
  {size => {
    // 如果你有自定义的size,以你的为准,没有则以SizeContext中默认的size
    const mergedSize = customizeSize || size;

    // 处理所有的className
    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>

Для стилей, а не непосредственно вlessфайл для записи какого-либо цвета или размера шрифта, дляant-designНапример, у них есть файл стиля, в котором хранится множество определенных переменных и даже файлы темы.Можно сказать, что если вы хотите настроить тему в то время, вам нужно только скопировать копию файла темы, а затем изменить его.Может напрямую удовлетворить потребности пользовательских тем ~

Как бы это сказать, на самом деле, после снятия некоторых сложных требований, относительный компонент карты намного проще.Если мы посмотрим еще на несколько компонентов, мы обнаружим, что он действительно ароматный.Исходный компонент все еще может быть разработан в этом Таким образом, по сравнению с тем, что было до того, как были разработаны компоненты с низким уровнем B, этот компонент выглядит слишком высоким. 🙃

следовать за

Оглядываясь назад, эта статья немного похожа на рукописную заметку, денег не много, ноОсновная цель — донести идею до всех: если у вас есть время, вы можете взглянуть на исходный код некоторых отличных компонентов.~ Аоли дать!

📢 Обновление, это постскриптум,Я больше не осмеливаюсь сказать, что могу написать компонент Button., это проблема и мысль, с которой я столкнулся при разработке компонента Button, надеюсь, он будет вам полезен~

Текущий прогресс

Текущий прогресс в группе тоже в порядке.Ведь все согласны с этим проектом,а версия v1 относительно свободна.Сначала будет выпущена базовая версия,а потом будут прорабатываться детали и оптимизация~

Ссылки по теме