Разговор о дизайне компонентов

Шаблоны проектирования

предисловие

Фронтенд-компонентное мышление не уникально, но является расширением фронтенд-технологии. Любой процесс разработки программного обеспечения в той или иной степени включает в себя некоторые из востребованных компонентов.

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

Перед началом статьи определите границы статьи

  • От начального проектирования до разработки компонентов
  • Принципы проектирования компонентов
  • Функциональное разделение компонентов и их плюсы и минусы
  • Границы проектирования компонентов
  • Как внедрить в конкретный бизнес
  • некоторые идеи
  • Суммировать

Мысли из вопроса интервью

面试官通常会问 写过前端通用组件吗?

Вы можете уверенно сказать: конечно!

эмм.. да?

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

Три этапа фронтенд-инжиниринга

1. Выбор библиотеки/фреймворка

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

2. Простая оптимизация сборки

image

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

3. Модульная разработка JS/CSS

image

После решения базовой эффективности разработки и эффективности эксплуатации начните рассматривать эффективность обслуживания.

Разделить и завоевать (разложение для уменьшения сложности) является важной идеей в разработке программного обеспечения и краеугольным камнем комплексной системы развития и обслуживания. Модульность является методом разделития в интернет-пределы и поколения

Таким образом, модульность подчеркиваетрасколоть, самая большая ценность — разделяй и властвуй, а это значит, что если вы захотите повторно использовать этот кусок кода в будущем, есть причина разделить их на модуль

Большая проблема непрерывно разбирается на различные мелкие проблемы для анализа и исследования, а затем объединяется воедино (принцип разделяй и властвуй)

Модульное решение

  • Модульный JS
无模块化->函数写法->对象写法->自执行函数->CommonJS/AMD/CMD->ES6 Module
  • Модульность CSS
css模块化是在less,sass等预处理器的支持下实现的

Достаточно ли этого?

Конечно, этого недостаточно

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

Есть некоторые проблемы с простым горизонтальным разделением модулей бизнес-функций.

  • Процессно-ориентированный код не способствует сопровождению по мере развития бизнеса
随着业务发展,”过程线“也会越来越长,其他项目成员根据各自需要,在”过程线“ 加插各自逻辑,最终这个页面的逻辑变得难以维护
我们需要摆脱【一泻而下】式的代码编写
  • Недостаточно иметь только модульность JS/CSS, и разделение и завоевание пользовательского интерфейса (страницы) также более насущны.
除了JS和CSS,界面也需要拆分,如何让模块化思想融入HTML语言

4. Компонентная разработка (тема этой статьи)

Эволюция компонентной разработки

Прежде чем продвигать концепцию компонентной разработки, она также прошла этап поиска лучших практик компонентной разработки.

Модульная структура страницы

image
Проще говоря, подумайте о странице как о роботе Lego, требующем сборки различных частей, а затем их соединения.

Реализовано в фактической разработке, как это

Мы можем получить информацию

  • Страница pageModel содержитtabContainer,listContainerа такжеimgsContainerтри модуля
  • Мы инкапсулируем разные типы моделей в соответствии с разной бизнес-логикой.
  • Каждая модель имеет свои данные, шаблоны, логику, считается законченным функциональным блоком

Хм? Почувствуйте запах компонентизации

N МСЛАМИ назад, на основе компонента Microsoft для компонента HTML

У истории всегда есть наследие 🐖

Еще N лет назад Microsoft предложила решение под названиемHTML Component

jsworke

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

Стандарт веб-компонентов

В то время "так называемые компоненты"

  • В настоящее время компоненты могут получить доступ к коллекции только в определенном функциональном блоке, а все ресурсы свободно разбросаны по трем файлам ресурсов.
  • И область действия компонента представлена ​​​​в глобальной области действия, отсутствие связности может легко конфликтовать с другими компонентами (например, простейший конфликт имен css).

Поэтому W3C не мог больше терпеть и разработал стандарт веб-компонентов, который определяет путь компонентизации в будущем.

примерно четыре части

  • <template>Возможность шаблона HTML для определения компонентов
  • Shadow Dom инкапсулирует внутреннюю структуру компонента и сохраняет его независимость
  • Пользовательский элемент предоставляет внешние теги компонентов для реализации пользовательских тегов.
  • import разрешает привязку компонентов и загрузку зависимостей

Давайте подумаем, какими возможностями должно обладать осуществимое практическое решение.

  • Высокая связность ресурсов (высокая связность внутри ресурсов компонентов, ресурсы компонентов контролируются их собственной загрузкой)
  • Независимость от области действия (внутренняя структура запечатана, не влияет на глобальные или другие компоненты)
  • Пользовательские метки (определяют, как используется компонент)
  • Можно комбинировать друг с другом (интеграция сборки между компонентами)
  • Нормализация интерфейса (интерфейсы компонентов имеют единую спецификацию или управление жизненным циклом)

Появляются три рамки

В сегодняшней фронтенд-экосистеме React, Angular и Vue составляют три трети мира.Даже если они позиционируются по-разному, основная общность заключается в предоставлении возможностей компонентизации, что в настоящее время является относительно хорошей практикой компонентизации.

1. Vue.js использует JSON для описания компонента
import PageContainer from './layout/PageContainer'
import PageFilter from './layout/PageFilter'

export default {
  install(Vue) {
    Vue.component('PageContainer', PageContainer)
    Vue.component('PageFilter', PageFilter)
  }
}

Также предоставляется формат файла SFC (Single File Component) «.vue».

<template>
//...
</template>

<script>
  export default {
    data(){}
  }
</script>

<style lang="scss">
//...
</style>
2. React.js изобрел JSX, напихал CSS и HTML в JS-файл
class Tabs extends React.Component {
    render() {
        if (!this.props.items) {
            console.error('Tabs中需要传入数据');
            return null;
        }
        const propId = this.props.id;
        return (
            <ul className={this.props.className}>
              <li>测试</li>
            </ul>
        );
    }
}
Angular.js Выберите расширение на оригинальном HTML
<input type="text" ng-model="firstname">

var app = angular.module('myApp', []);
app.controller('formCtrl', function($scope) {
    $scope.firstname = "John";
});

Интеграция ресурсов по стандарту

image

Имеет следующие характеристики

  • Каждый компонент соответствует каталогу, и различные ресурсы, необходимые компоненту, хранятся поблизости в этом каталоге (наиболее ценная разработка программного обеспечения).
  • Каждая независимая визуальная/интерактивная область на странице считается компонентом;
  • Поскольку компоненты независимы, их можно свободно комбинировать;
  • Страница — это контейнер компонентов, отвечающий за объединение компонентов для формирования полнофункционального интерфейса;
  • Когда компонент не нужен или вы хотите заменить компонент, вы можете удалить/заменить весь каталог

Схема структуры приложения

image

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

Модульность против компонентизации

Из общей концепции

  • Модульность — это идея «разделяй и властвуй», а привлекательность — в разъединении, которое обычно относится к модулям js, таким как модули, используемые для форматирования времени.
  • Компонентизация — это средство реализации идеи модульности, а привлекательность — повторное использование, в том числеtemplate,style,script, скрипт может состоять из различных модулей

С точки зрения повторного использования

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

С точки зрения исторического развития

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

Принципы проектирования компонентов

При компонентном решении нам необходимо компонентное проектное мышление, которое является своего рода [организацией], помогающей нам эффективно разрабатывать и интегрировать.

  1. стандартный
任何一个组件都应该遵守一套标准,可以使得不同区域的开发人员据此标准开发出一套标准统一的组件
  1. независимость
描述了组件的细粒度,遵循单一职责原则,保持组件的纯粹性
属性配置等API对外开放,组件内部状态对外封闭,尽可能的少与业务耦合
  1. Повторное использование и простота использования
UI差异,消化在组件内部(注意并不是写一堆if/else)
输入输出友好,易用
  1. Следуйте кратко и лаконично

  2. Применить правило SPOT

Single Point Of Truth,就是尽量不要重复代码,出自《The Art of Unix Programming》
  1. Избегайте раскрытия внутренней реализации компонента
  2. Избегайте манипулирования DOM напрямую, избегайте использования ref
使用父组件的 state 控制子组件的状态而不是直接通过 ref 操作子组件

  1. Проверить правильность параметров на входе, и проверить корректность возврата на выходе
  2. Принцип ациклической зависимости (ADP)

Схематическая диаграмма круговой зависимости, вызванная неправильным дизайном

image

влияние

Высокая степень связанности между компонентами, сложное интеграционное тестирование Одна модификация, повсеместное влияние, длительное время выполнения Поскольку между компонентами существует круговая зависимость, возникает проблема «курица или яйцо».

Тогда, если мы действительно столкнемся с такой проблемой, мы должны подумать, как с ней справиться.

удалить кольцевые зависимости

Наша задача — найти все затронутые компоненты по обратным зависимостям.

Создайте новый компонент с общей зависимостью

image

  1. Принцип стабильной абстракции (SAP)
- 组件的抽象程度与其稳定程度成正比,
- 一个稳定的组件应该是抽象的(逻辑无关的)
- 一个不稳定的组件应该是具体的(逻辑相关的)
- 为降低组件之间的耦合度,我们要针对抽象组件编程,而不是针对业务实现编程
  1. Избегайте избыточных состояний
如果一个数据可以由另一个 state 变换得到,那么这个数据就不是一个 state,只需要写一个变换的处理函数,在 Vue 中可以使用计算属性

如果一个数据是固定的,不会变化的常量,那么这个数据就如同 HTML 固定的站点标题一样,写死或作为全局配置属性等,不属于 state

如果兄弟组件拥有相同的 state,那么这个state 应该放到更高的层级,使用 props 传递到两个组件中

  1. Разумные зависимости
父组件不依赖子组件,删除某个子组件不会造成功能异常

  1. Параметры выравнивания
除了数据,避免复杂的对象,尽量只接收原始类型的值
  1. хороший дизайн интерфейса
把组件内部可以完成的工作做到极致,虽然提倡拥抱变化,但接口不是越多越好

如果常量变为 props 能应对更多的场景,那么就可以作为 props,原有的常量可作为默认值。

如果需要为了某一调用者编写大量特定需求的代码,那么可以考虑通过扩展等方式构建一个新的组件。

保证组件的属性和事件足够的给大多数的组件使用。

  1. API максимально соответствует известным концепциям

Разделение функциональных компонентов

Тогда с помощью «API» проектирования компонентов можно будет разрабатывать высококачественные компоненты?

Самая большая нестабильность компонентов исходит от уровня представления Компонент делает только одну вещь и распределяет обязанности в зависимости от функций.

Как правило, я бы разделил компоненты на следующие категории

  • Базовые компоненты (обычно решаются в библиотеке компонентов)
  • Компонент-контейнер (Контейнер)
  • Компоненты дисплея (без сохранения состояния)
  • бизнес-компонент
  • Общие компоненты
    • Компоненты пользовательского интерфейса
    • логический компонент
  • Компоненты высшего порядка (HOC)

основные компоненты

Чтобы заставить разработчиков уделять больше внимания бизнес-логике, появилось множество отличных библиотек компонентов пользовательского интерфейса. Напримерantd,element-ui, нам нужно позвонить только на API для удовлетворения большинства бизнес-сценариев, передняя роль позади, а развитие становится проще

компонент контейнера

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

image

Функции

  • Подкомпоненты в компонентах-контейнерах часто имеют бизнес-зависимости или зависимости от данных.
  • Централизованное/унифицированное управление состоянием, предоставление данных другим презентационным/контейнерным компонентам (действующие в качестве источника данных) и логика поведения обработки (получение обратных вызовов)
  • Если используется управление глобальным состоянием, бизнес-компоненты внутри контейнера могут сами вызывать бизнес обработки глобального состояния.
  • Коммуникация и другая коммуникация между бизнес-модулями, такая как коммуникация и т. д., выступают в качестве дочернего компонента связи.
  • Шаблоны в основном представляют собой набор компонентов нижнего уровня, редко содержатDOMЭтикетка
  • Разделение вспомогательного кода

Выражение 🌰 (вью)

<template>
<div class="purchase-box">
  <!-- 面包屑导航 -->
  <bread-crumbs />
  <div class="scroll-content">
    <!-- 搜索区域 -->
    <Search v-show="toggleFilter" :form="form"/>
    <!--展开收起区域-->
    <Toggle :toggleFilter="toggleFilter"/>
    <!-- 列表区域-->
    <List :data="listData"/>
  </div>
</template>

компоненты без сохранения состояния

Он в основном показывает, как визуализируются компоненты, например, простой процесс визуализации шаблона.

image

Функции

  • Принимает только данные и функции обратного вызова через реквизиты, не выступает в качестве источника данных.
  • Может содержать компоненты отображения и контейнера и, как правило, иметь теги Dom и стили CSS.
  • Обычно используйте props.children(react) или slot(vue) для включения других компонентов.
  • Отсутствие зависимостей от третьих лиц (может иметь компонент уровня приложения)
  • Он может иметь состояние, а его внутреннее состояние можно манипулировать и изменять в течение его жизненного цикла.Он несет единую ответственность и передает поведение, которое не принадлежит ему, через обратные вызовы и позволяет родительскому процессу обрабатывать его (события поиска компонентов поиска/события добавления форм)

Выражение 🌰 (вью)

 <template>
 <div class="purchase-box">
    <el-table
      :data="data"
      :class="{'is-empty': !data ||  data.length ==0 }"
      >
      <el-table-column
        v-for = "(item, index) in listItemConfig"
        :key="item + index" 
        :prop="item.prop" 
        :label="item.label" 
        :width="item.width ? item.width : ''"
        :min-width="item.minWidth ? item.minWidth : ''"
        :max-width="item.maxWidth ? item.maxWidth : ''">
      </el-table-column>
      <!-- 操作 -->
      <el-table-column label="操作" align="right" width="60">
        <template slot-scope="scope">
          <slot :data="scope.row" name="listOption"></slot>
        </template>
      </el-table-column>
      <!-- 列表为空 -->
      <template slot="empty">
        <common-empty />
      </template>
    </el-table>
    
 </div>
  </template>
<script>
  export default {
    props: {
        listItemConfig:{ //列表项配置
        type:Array,
        default: () => {
            return [{
                prop:'sku_name',
                label:'商品名称',
                minWidth:200
            },{
                prop:'sku_code',
                label:'SKU',
                minWidth:120
            },{
                prop:'product_barcode',
                label:'条形码',
                minWidth:120
            }]
      }
    }}
  }
</script>

бизнес-компонент

Обычно он абстрагируется на основе минимального бизнес-состояния.Некоторые бизнес-компоненты также имеют определенную возможность повторного использования, но большинство из них являются одноразовыми компонентами.

image

Общие компоненты

Компоненты, которые могут быть общими в одном или нескольких приложениях

Компоненты пользовательского интерфейса

  • Компоненты класса расширения интерфейса, такие как всплывающие окна

image

Особенности: сильное повторное использование, связь с внешним миром только через интерфейсы компонентов, такие как реквизиты, события и слоты.

Выражение 🌰 (вью)

<template>
  <div class="empty">
    <img src="/images/empty.png" alt>
    <p>暂无数据</p>
  </div>
</template>

логический компонент

  • Логическая коллекция функций, не содержащая слоя пользовательского интерфейса.

Компоненты высшего порядка (HOC)

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

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

представлен диаграммой

jsworke

Компонент высокого порядка React — это широко используемый пакет компонентов, Vue — официальный компонент высокого порядка, созданныйkeep-aliveСохранность данных достигается за счет поддержания кеша, но HOC не рекомендуется :(

在 React 中写组件就是在写函数,函数拥有的功能组件都有

Vue更像是高度封装的函数,能够让你轻松的完成一些事情,但与高度的封装相对的就是损失一定的灵活,你需要按照一定规则才能使系统更好的运行

Выражение 🌰 (реагировать)

Анимация скольжения серии автомобилей марки

Различные компоненты работают вместе, образуя бизнес-модули.

image

компонент контейнера/дисплея

Сравнительная таблица

image

Представление концепции компонентов контейнера - это просто лучший способ организации

  • Компонент-контейнер специально отвечает за связь с хранилищем, передачу данных компоненту отображения через реквизиты, и если компоненту отображения необходимо обновить данные, ему необходимо передать обратный вызов компоненту-контейнеру и выполнить определенные операции (бизнес-логика ) в компоненте-контейнере для получения результата обновления
  • Презентационные компоненты больше не связаны напрямую с хранилищем, но необходимые данные и методы определяются через интерфейс реквизита, а возможность повторного использования и правильность более гарантированы.
  • Если презентационный компонент связывается напрямую с магазином, тогда презентационный компонент будет ограничен, потому что ваши поля в магазине имеют ограниченное время и место его использования.
  • Выполняют свои обязанности, ошибаться нелегко, даже если они совершают ошибки, они могут быстро найти проблему

В этом случае, когда я ввожу компоненты контейнера и когда я ввожу компоненты отображения

Когда вводить компоненты контейнера

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

Различие между компонентами-контейнерами и компонентами представления строго не определено, их отличие не техническое, а целевое.

Вот несколько пунктов для справки

  • Компоненты-контейнеры, как правило, имеют состояние, компоненты представления, как правило, не имеют состояния, это не жесткое правило, все они могут иметь состояние.
  • Не воспринимайте разделение компонентов-контейнеров и компонентов представления как догму. Если вы не уверены, является ли компонент компонентом-контейнером или компонентом представления, пока не разделяйте его. это как компонент презентации. Не волнуйтесь!
  • Это непрерывный процесс рефакторинга, не пытайтесь сделать все правильно сразу, и привыкание к этому шаблону развивает интуитивное понимание того, когда вводить контейнер, точно так же, как вы знаете, когда инкапсулировать функцию.

Плюсы и минусы разделения функций компонентов

преимущество

  • лучшее разделение интересов
用这种方式写组件,你可以更好的理解你的app和你的ui,甚至会逐渐形成你自己的开发套路
  • Высокая возможность повторного использования
一个组件只做一件事,解除了组件的耦合带来更高复用性
  • Это цветная версия приложения, дизайнер может настроить свой пользовательский интерфейс по своему усмотрению, не меняя логику приложения.
  • Это заставляет вас извлекать «компоненты макета» для большей простоты использования.
  • повысить надежность
由于展示组件和容器组件是通过prop接口来连接,可以利用props的校验机制来增强代码的可靠性,混合的组件就没有这种好处

举个🌰(Vue)
  props: {
    editData: Object,
    statusConfig: {
      type: Object,
      default() {
        return {
          isShowOption: true, //是否有操作栏
          isShowSaveBtn: false
        };
      }
    }
  }
  • Тестируемость
组件做的事情更少了,测试也会变得容易
容器组件不用关心UI的展示,只关心数据和更新
展示组件只是呈现传入的props,写单元测试的时候也非常容易mock数据层

так называемые недостатки

  • Из-за разделения компонентов контейнера/компонентов дисплея на начальном этапе будут добавлены некоторые затраты на обучение.
  • Из-за необходимости инкапсулировать контейнер и обернуть некоторые данные и интерфейсы в компонент дисплея, это увеличит рабочую нагрузку.
  • Объявление свойств внутри презентационных компонентов требует небольшой работы.

В долгосрочной перспективе плюсы перевешивают минусы

Границы проектирования компонентов

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

Уровень страницы не должен быть вложен более чем в три слоя и не должен чрезмерно проектироваться.

超过三层之后可见组件的数据传递的过程就会变得越复杂

Можно ли (обязательно) разделить этот компонент?

  • Степень детализации взвешивается в соответствии с реальной ситуацией: слишком маленькая будет увеличивать стоимость обслуживания, а слишком большая будет негибкой и многократно используемой.
  • Каждый компонент должен иметь свою уникальную цель разделения, некоторые для реализации мультиплексирования, некоторые для инкапсуляции сложности и четкой реализации бизнеса.
  • Основой разделения на компоненты обычно является бизнес-логика и функции.Необходимо учитывать, ясна ли взаимосвязь между компонентами и степень повторного использования.
  • Если это всего несколько строк кода, вы можете в конечном итоге создать дополнительный код для его разделения, так ли это необходимо? Превышают ли выгоды от этого затраты?
  • Если ваша текущая логика вряд ли где-то появится, лучше ее встроить, а вытащить всегда можно, если надо, ведь компонентизации нет конца
  • Будет ли затронута производительность? Если статус частый, и в данный момент в относительно близком компоненте, то во избежание производительности лучше извлечь.
  • Нарушает ли он логически значимую сущность, и если он извлечен, какова вероятность повторного использования кода?

Можно ли дополнительно уменьшить зависимости этого компонента?

Сокращение зависимостей компонентов может улучшить возможность повторного использования компонентов.

Является ли этот компонент навязчивым для других компонентов?

  • Недостаточная инкапсуляция или собственные операции за пределами границ могут привести к вторжению извне.
  • Компонент не должен напрямую влиять на другие одноуровневые компоненты.
较常见的一种情况是:组件运行时对window对象添加resize监听事件以实现组件响应视窗尺寸变化事件,这种需求的更好替代方案是:组件提供刷新方法,由父组件实现调用

次优的方案是,当组件destroy前清理恢复

Можно ли повторно использовать этот компонент в других подобных сценариях?

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

Когда этот компонент будет использоваться другими, что он подумает?

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

Если бизнесу не нужна эта функция, легко ли ее очистить?

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

Различные критерии, упомянутые выше, описывают только концепцию разработки, а также могут рассматриваться как спецификация разработки.Если вы согласны с этой спецификацией и резонируете с ее стратегией «разделяй и властвуй», то мы можем продолжить разговор о ней.

задай себе вопрос

Как, по-твоему, выглядит относительно совершенный компонент?

Как внедрить в конкретный бизнес

База дивизиона

Уточните основу разделения компонентов, в настоящее время существует два

  • По бизнес-подразделению
  • По технологии
  1. Я разрабатываю дерево компонентов в своем приложении больше в соответствии с бизнесом, может быть, рисую эскиз или xmind, это может помочь мне увидеть общую ситуацию.
  2. Уточните границы каждого компонента, дизайн внутреннего состояния, дизайн реквизита и взаимосвязь с другими компонентами (события, которые необходимо вызвать)
  3. Уточнить позиционирование и функциональное разделение каждого компонента, а также спроектировать механизм связи между родительскими и дочерними компонентами и одноуровневыми компонентами.
  4. важничать
  5. Полка есть, начните заполнять пробелы

Шаблон резки (модульная структура страницы)

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

jsworke

Вообще говоря, его можно разделить на Часть 1, Часть 2, Часть 3.

предварительная разработка

<template>
  <div id="app">
    <div class="panel">
      <div class="part1 left">
        <!--内容-->
      </div>
      <div class="part1 right">
        <!--内容-->
      </div>
      <div class="part1 right">
        <!--内容-->
      </div>
  </div>
</template>

вопрос:

  • Большой объем кода, сложно поддерживать, сложно тестировать
  • некоторое повторение

Упрощать

<template>
  <div id="app">
      <part1 />
      <part2 />
      <part3 /> 
  </div>
</template>

выгода:

  • Это тонкое улучшение является революционным по сравнению с предыдущими подходами.
  • Решите проблему сложного тестирования и сложного обслуживания

вопрос:

  • Не решает проблему дублирования кода, который разбит на модули и имеет низкую возможность повторного использования

Но я видел код многих проектов, этим я и занимаюсь, кажется, я делал компонентизацию, и абстракция неплохая (@_@)

Абстракция компонента

У них похожие внешние слои, часть 2 и часть 3 имеют более похожие заголовки, за исключением бизнес-контента, они абсолютно одинаковы.

🌰 (вью)

<template>
  <div class="part">
    <header>
      <span>{{ title }}</span>
    </header>
    <slot name="content" />
  </div>
</template>


Все абстрактные данные в детали делаем пропсами, а слот используем как шаблон Затем мы разрабатываем соответствующие Part1, Part2

🌰 (вью)

<template>
  <div id="app">
      <part title="亦舒">
        <div slot="content">----</div>
      </part>
      <part title="兴隆臻园户型">
        <div slot="content">-----</div>
      </part>
  </div>
</template>

Более показательный пример

jsworke

  • Где определяются различия пользовательского интерфейса?

Обрабатывается на уровне бизнес-логики

首先要明确一点,这些差异并不是组件本身造成的,是你自己的业务逻辑造成的,所以容器组件(父组件)应该为此买单
  • Где определяется разница в данных?

Объедините сам компонент и бизнес-контекст, чтобы разумно устранить различия внутри компании.

比如part3中,其他的part只有一个类似更多>>的link,但是它却有多个(一居,二居...)
这里我推荐将这种差异体现在组件内部,设计方法也很多:
比如可以将link数组化为links;
比如可以将更多>>看作是一个default的link,而多余的部分则是用户自定义的特殊link,这两者合并组成了links。用户自定义的默认是没有的,需要引用组件时进行传入。


  • Соглашение об именах компонентов?

На ранней стадии проектирования компонента он должен иметь название несвязанного бизнеса.

一个通用的或者说未来可能通用的,要有相对合理的命名,比如 Search,List,尽量不要出现与业务耦合过深的业务名词,通用组件与业务无关,只与自身抽象的组件有关
我们在设计组件初期,就应该有这种思想,等到真正可以抽出公用组件了,再去苦逼的名改名字?
库通常都想让广大开发者用,我们在设计组件时,可以降低标准到先做到你的整个APP中通用

Детальный учет разделения компонентов (со степенью извлечения)

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

jsworke

Чтобы реализовать компонент значка, он состоит из двух частей.

  • кнопка
  • Советы в правом верхнем углу (маленькая красная точка/значок)

Оба несут единственную ответственность и могут быть абстрагированы в отдельный компонент, но обычно не

因为同一个app的风格必将是统一的,除此之外没别的应用场景了,就像上文所说的,抽离组件之前,多问自己为什么以及投入/产出比,没有绝对的规则

tips

Компоненты с одной ответственностью должны быть основаны на повторном использовании.Для неповторно используемых компонентов с одной ответственностью мы можем использовать их только как внутренние компоненты независимых компонентов.

Пример веб-сайта подержанных автомобилей, отражающий его детализированную структуру.

jsworke

Подумайте о том, как бы вы спроектировали, если бы у вас это получилось... Я разработал это таким образом

jsworke

index.js(react)

<div className="select-brand-box" onTouchStart={touchStartHandler} onTouchMove={touchMoveHandler} onTouchEnd={touchEndHandler.bind(this, touchEndCallback)}>
     <NavBar></NavBar>
     <Brand key="brands-list" {...brandsProps} />
     <Series key="series-list" {...seriesProps} >
 </div>
 
 export default BrandHoc(index);

Brand.js(react)

<div className="brand-box">
    <div className="brand-wrap" ref="brandWrap">
        <p className="brands-title hot-brands-title">热门品牌</p>
        <FlexLayout onClick={hotBrandClick}>
            <HotBrands HotBrands={hotBrands} />
        </FlexLayout>
        {!isHideStar && <UnlimitType {...unlimitProps} />}
        <AllBrands {...brandsProps} />
    </div>
    <AsideLetter {...asideProps} />
    {showPop ? <PopTips key="pop-tips" tip={currentLetter} /> : null}
    {showBrandLoading ? <Loading /> : null}
</div>
            

FlexLayout.js(react)

jsworke

Этот пример охватывает почти все правила

  • Прежде всего, дизайн компонентов разделен по бизнесу, поэтому правая буквенная навигация (AsideLetter) не имеет самого внешнего компонента-контейнера, иначе коммуникационная задача займет часть пространства, по сути, это решение
  • Компонент входа — это компонент-контейнер, по сути, это правило и носитель бизнес-логики.
  • За исключением компонента контейнера, другие компоненты были извлечены для общего пользования.Существует много подобных сценариев для платформ подержанных автомобилей.

jsworke

  • На площадке по продаже автомобилей много похожих изображений и текстов, а формы разные.Сценарии применения широкие, качай! Различия в пользовательском интерфейсе перевариваются внутри компонента, см. FlexLayout.js, учитывая реквизиты по умолчанию.
  • Как решить проблемы с коммуникацией, вызванные слишком большим количеством извлекаемых компонентов (по бизнесу)? Это означает, что вам нужно добавить компонент-контейнер, который может управлять состоянием.В приведенном выше примере бренд и серия также являются компонентами-контейнерами, которые отвечают за управление размером подкомпонентов.
  • Детальные соображения, учитывающие соотношение оплаты к результату
<p className="brands-title hot-brands-title">热门品牌</p> 只有一行,直接写就完了

  • Процесс извлечения компонентов — это процесс бесконечного приближения к компонентам без состояния (презентативным).

Общие Соображения

Форма (UI) компонента всегда постоянно меняется, но его поведение (логика) фиксировано, поэтому один из секретов универсального компонента — передать контроль над DOM-структурой разработчику, а сам компонент отвечает только за поведение и самую базовую структуру DOM

Это заметный каштан

Однажды вы получаете такой запрос

jsworke

Счастливый, простой, законченный текст

Вдруг в один прекрасный день есть такая необходимость

jsworke

эмм.. настраиваемый? Предыдущий выбор не работает, что делать? Вы хотите изменить предыдущий или написать другой? Как только это происходит, это доказывает, что предыдущие компоненты должны быть переработаны.

Ключом к достижению универсального дизайна является отказ от контроля над Домом.

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

Универсальный дизайн задает значения по умолчанию, оставляя решения о структуре Dom за разработчиком.

Вот свежеиспеченный (вью) 🌰

Компонент списка

jsworke

Родительский компонент 🌰(vue) и слот

模版(伪代码)
<template>
<List :data="tableData[item.type]" :loading="loading" @loadMore="loadMore" :noMore="noMore">
    <a v-if="item.type == 0" slot="listOption" slot-scope="childScope" class="edit-btn" @click="edit(childScope.data)" v-bind:key="childScope.data.id">{{Status[childScope.data.status]['text']}}</a>
</List>
</template>

config(伪代码)
export const Status = {
  //....
  1: {
    label: '草稿',
    type: '',
    text: '编辑',
    class: 'note'
  }}
  //...

Еще один каштан (vue)

jsworke

  • Диалог отвечает только за базовую логику и передает управление бизнесу, а то, что нужно вашему бизнесу, обрабатывается в компоненте-контейнере (уровень бизнес-логики).

Не могу не привести негативный пример рок-бизнеса

jsworke

Трудность — это не что иное, как два аспекта проблемы.

  1. Отказ от передачи управления
  2. Нет документации API

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

Просто на текущем этапе доработки UI наша нагрузка изменилась с простого изменения стиля на его отмену, без подробной документации нагрузка удвоилась в N раз за мгновение.

Эффективно используйте шаблоны проектирования

На самом деле вначале я специально не применял шаблоны проектирования, это было полностью обусловлено бизнесом. Вы наверняка видели что-то подобное

jsworke

Раз такой логики больше, она связана с бизнесом и больше связана с бизнесом, компонент естественно не будет иметь общности, даже если не учитывать общности, писать будет утомительно?

Подумайте, не лучше ли было бы написать так

config(伪代码)
export const Status = {
  4: {
    label: '部分入库',
    type: '',
    text: '查看'
  }
}
模版(vue)
<a v-if="item.type == 0" slot="listOption" slot-scope="childScope" class="edit-btn" @click="edit(childScope.data)" v-bind:key="childScope.data.id">{{Status[childScope.data.status]['text']}}</a>

В мире нет шаблона дизайна, и сколько бы людей его ни написали, он будет выделяться и останется в истории! Мало того, некоторые, казалось бы, сложные предприятия могут сэкономить вам много js, если вы разумно спроектируете элементы конфигурации.

некоторые идеи

Низкоуровневая система поддержки бизнеса, такая как Rockstone, неотделима от большого количества списков, запросов, правок, деталей и т. д. Обычно я трачу 30 секунд на настройку полки, например, но не ограничиваясь следующим

jsworke

  • index: запись модуля (берет на себя ответственность контейнера)
  • api: API для всего бизнеса
  • компоненты коллекция бизнес-компонентов
1. Form:表单 一般会被add.vue(编辑) 和edit.vue(详情)引用
2. List:列表
3. Search: 搜索组件
4. 其他业务中有但却没看到的基本上都已经抽离到common了 比如面包屑导航,收起展开功能等
  • Различные конфигурации страницы libs

Конкретное воплощение (модуль только что отрефакторен Роком)

Структурная схема модуля «Закупки»

image

form

image

edit

image

Сколько бы состояний ни было, оно сохраняется только в слое редактирования контейнера.

причина для этого

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

Суммировать

  • Для компонентного проектирования, конечно, необходима адекватная подготовка, но в реальном мире важнее всего осязаемые результаты, а компонентный дизайн не должен быть чрезмерно спроектированным или застойным. хорошо.
  • У вас будет свободное время, чтобы подумать о неидеальном коде на раннем этапе, и это может послужить основой для нашего движения вперед.
  • Технология меняется, но ядро ​​компонентизации не изменилось.Цель состоит в том, чтобы выполнить цели повторного использования, развязки, инкапсуляции и абстракции с дизайном API, максимально приближенным к оригиналу, и в конечном итоге служить развитию, повысить эффективность и уменьшить количество ошибок.
  • Компонентизация — это наслоение реализаций и более эффективный способ комбинирования кода.
  • Компонентизация — это реорганизация и оптимизация ресурсов, чтобы сделать управление ресурсами проекта более разумным, легко подключаемым, легко интегрируемым, легко удаляемым, легко удаляемым и воссоединяемым.
  • Эта идея упрощения сложности отражена в бэкенд-разработке как микросервисы, а во фронтенд-разработке как компонентизация.
  • Компонентизация способствует модульному тестированию и эффективности самотестирования, а также удобна для рефакторинга.
  • Новички могут напрямую назначать компоненты для разработки и тестирования, вместо того, чтобы быть знакомым со всем проектом.Начиная с разработки компонента, новички могут быстро ознакомиться с проектом и понять спецификации разработки
  • Вашей непосредственной обязанностью может быть написание кода, но вашей конечной целью является создание продукта.

Последнее слово

Компонентизация не имеет конца, день за днем

Ссылка на ссылку