Что такое концентрат, на котором работает React, и почему его стоит попробовать?

React.js
Что такое концентрат, на котором работает React, и почему его стоит попробовать?

welcome star

Твоя звезда будет моим величайшим духовным ободрением,приветственная звезда🥺🥺🥺

последовательность

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

концентрат обладает следующими свойствами

  • Основные API-интерфейсы немногочисленны и просты, с мощными функциями, просты в использовании, не требуют вмешательства и просты в отладке.
  • Предоставляет единый источник достоверной информации для глобальной модульности
  • Поддерживает метод 0-вторжения и постепенно реорганизует существующий код реагирования
  • Расширенные функции, такие как шина событий, вычисления, просмотр и двусторонняя привязка к компонентам.
  • Идеальная поддержка функциональных компонентов
  • Основываясь на эталонном позиционировании и широковещании состояния, он поддерживает детализированную подписку на состояние, а эффективность рендеринга является выдающейся.
  • Поддержка промежуточного программного обеспечения, которое может расширить ваши персонализированные плагины для обработки изменений данных.
  • Поддержка любой версии реакции 0.10+;

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

Проработанная концепция модульного дизайна

state

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

reducer

Гибкость в способе изменения данных — это один из сюрпризов, которые concent преподносит пользователям, потому что суть concent — взять на себя управление.setStateВыполняйте управление состоянием, чтобы пользователи могли пользоваться преимуществами управления состоянием без немедленного изменения существующего кода при доступе к содержимому.reducerФункция изменяет состояние, что также является рекомендуемой передовой практикой, которая может полностью отделить отрисовку пользовательского интерфейса и бизнес-логику, потому чтоreducerФункция по сутиsetStateВарианты формулировки, поэтому акцент всегда возвращается для обновления состояния фрагмента, а также потому, что сопровождениеreducerФункции вызывают друг друга и могут произвольно комбинироваться, поэтому пользователям может быть разрешено произвольное сокращение по мере необходимости.reducerОбновите детализацию функции до состояния, а затем сформируйте отношение цепного вызова, а затем передайтеdispatchручка для запускаreducerфункция

cc-dispatch

Если уровень цепного вызова слишком глубокий, это вызовет много отрисовок.Из рисунка выше видно, что есть 3 функции, которые возвращают новое состояние фрагмента, что приводит к 3 отрисовкам, поэтомуconcentтакже предоставитьlazyDispatchобрабатывать, чтобы дать пользователю один из вариантов, чтобы вызвать паруreducerвызов функции,concentВ процессе передачи все состояния, принадлежащие одному и тому же модулю в текущей цепочке вызовов, будут автоматически кэшированы и объединены, а однократная отправка не будет производиться до конца цепочки вызовов.

cc-lazy-dispatch

computed

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

watch

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

init

Мы знаем, что определение состояния синхронно,initРазрешить пользователямstateСделайте возможность получения и перезаписи асинхронно.Обратите внимание, что если в это время есть экземпляр модуля, то после перезаписи состояния модуля,concentЭти состояния будут автоматически транслироваться в соответствующие экземпляры.Точно так же, если они не существуют, при создании некоторых экземпляров модуля эти экземпляры будут синхронизированы с последним состоянием модуля, поэтому, когда у нас есть некоторые состояния, мы делаем не нужно зависеть от зависания экземпляра. загрузить и запуститьcomponentDidMountКогда вы придете, чтобы получить его, вы можете обновить инициализацию состояния до модуляinitвнутри

cc-lazy-dispatch

Гибкое сопоставление модулей и компонентов

Модуль — это концепция, которая существует до компонента. Когда у нас есть определение модуля, мы можем обеспечить сильную поддержку компонента.concentчерезregisterФункция регистрирует компонент реакции как компонент концентрата (также называемый классом концентрата).

cc-lazy-dispatch

При регистрации можно указать эксклюзивный модуль.По идее, мы должны поддерживать чистое соответствие между компонентами и модулями, то есть компонент посвящен модулю, потребляет данные модуля и работает с модулем, которому он принадлежит.reducerфункция, но в реальной сцене может быть много компонентов, которые потребляют и изменяют данные в нескольких модулях, поэтомуconcentТакже позволяет пользователямconnectОпределите, чтобы указать другие модули, подключенные к компоненту. Единственное отличие состоит в том, что контекст по умолчанию дескриптора вызова указывает на его собственный модуль. Если вам нужно вызвать методы других модулей, вам нужно отобразить указанное имя модуля.

@register('Foo', {module:'foo', connect:{bar:'*'}})
class Foo extends Component(){
  onNameChange = (name)=>{
    this.$$dispatch('changeName', name);//默认调用的foo模块reducer里的changeName方法

    this.$$dispatch('bar/changeName', name);//指定bar模块, 调用bar模块的reducer里的changeName方法修改bar模块的数据
  }
}

cc-ccclass-module
дляCcClassНапример, потому что вызовsetStateВы можете изменить хранилище, чтобы данные вводились непосредственно в хранилище.state, для данных других модулей вводится вconnectedState, Это не только поддерживает изоляцию данных между модулем и другими модулями, но также позволяет пользователям легко использовать данные нескольких модулей.
cc-class-and-instance-state

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

cc-class-and-store

Более дружественная поддержка функций

существуетhookПосле того, как предложение было реализовано, существующее реагирующее сообщество постепенно перешло от написания компонентов класса к написанию функциональных компонентов, но по мереVue Function-based API RFCсказал,hookОчевидная проблема создания множества временных функций и генерации множества замыканий, а также предоставления вспомогательных функций.useMemo/useCallbackи т. д. для решения таких проблем, как чрезмерное обновление или захват значений с истекшим сроком действия,setupсхеме каждый экземпляр компонента будет вызываться только один раз при инициализации, а состояние сохраняется по ссылке в замыкании setup().

Сочетание вышеперечисленногоsetupидеи и преимущества,concentпротивreactФункциональная составляющая введенияsetupМеханизм был улучшен и он также вызывается только один раз при создании экземпляра компонента.Можно определять и возвращать различные методы.Эти методы будут собраны в контекстеsettingsобъекта и дополнительно разрешитьsetupопределено вeffect,computed,watchфункции (конечно, это экземпляр уровняcomputedа такжеwatch)

Онлайн-пример

Определение пользовательского интерфейса

const AwardPanelUI = (props) => {
  return (
    <div style={stBox}>
      {/** 其他略 */}
      <div>displayBonus: {props.displayBonus}</div>
    </div>
  );
};

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

const setup = ctx => {
  //定义副作用,第二位参数写空数组,表示只在组件初次挂载完毕后执行一次
  ctx.defineEffect(ctx => {
    ctx.dispatch('init');
    //返回清理函数,组件卸载时将触发此函数
    return () => ctx.dispatch('track', 'user close award panel')
  }, []);

  /** 也支持函数式写法
    ctx.defineWatch(ctx=>{
      return {...}
    });
   */
  ctx.defineWatch({
    //key inputCode的值发生变化时,触发此观察函数
    'inputCode':(nevVal)=> ctx.setState({msg:'inputCode 变为 '+nevVal })
  });
  ctx.defineComputed({
    //key inputCode的值发生变化时,触发此计算函数
    'inputCode':(newVal)=>`${newVal}_${Date.now()}`
  });

  //定义handleStrChange方法
  const handleStrChange = (e) => {
    const inputCode = e.currentTarget.value;

    //两种写法等效
    ctx.dispatch('handleInputCodeChange', inputCode);
    // ctx.reducer.award.handleInputCodeChange(inputCode);
  }

  //定义init函数
  const init = ctx.reducer.award.init;
  //const init = ()=> ctx.dispatch('init');

  //setup会将返回结果放置到settings
  return { handleStrChange, init };
}

определение mapProps

//函数组件每次渲染前,mapProps都会被调用,帮助用户组装想要的props数据
const mapProps = ctx => {
  //将bonus的计算结果取出
  const displayBonus = ctx.moduleComputed.bonus;
  //将settings里的 handleStrChange方法、init方法 取出
  const { handleStrChange, init } = ctx.settings;
  //将inputCode取出
  const { inputCode, awardList, mask, msg } = ctx.moduleState;

  //从refConnectedComputed获取实例对模块key的计算值
  const { inputCode:cuInputCode } = ctx.refComputed.award;

  //该返回结果会映射到组件的props上
  return { msg, cuInputCode, init, mask, inputCode, awardList, displayBonus, handleStrChange }
}

Подключить функциональные компоненты

const AwardPanel = connectDumb({setup, mapProps, module:'award'})(AwardPanelUI);

Действительно ли крючок является ответом?

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

В то же время функциональное программирование более удобно дляtypescriptсделать вывод типа,concentДружественная поддержка функциональных компонентов, позволяющая пользователямclassа такжеfunctionвыбрать между по мере необходимости,concentтакже позволяет определитьstateзаниматься местным государственным управлением, поэтому послеconnectDumbзавернутыйfunctionКомпонент, который может читать и записывать как локальное состояние, так и состояние хранения, какая лучшая причина для его использованияhookПочему бы нет?

const AwardPanel = connectDumb({
  //推荐写为函数式写法,因为直接声明对象的话,concent也会对其做深克隆操作
  //state:()=>({localName:1});
  state:{localName:1},
  setup, 
  mapProps, 
  connect:{award:'*'}
})(AwardPanelUI);

//code in setup
const setup = ctx =>{
  const changeLocalName = name => ctx.setState({localName});
  return {changeLocalName};
}

//code in mapProps
const mapProps = ctx =>{
  const localName = ctx.state.localName;
  return {localName}; 
}

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

БудуconcentдоступreactПриложение очень легкое и простое.Для существующего реагирующего приложения вам не нужно изменять какой-либо код существующего реагирующего приложения, вам нужно только сначалаconcentЗапустите его, вы можете использовать его, вам не нужно оборачивать его в верхний слойProviderкомпоненты, такие как предоставление глобального контекста, поскольку запускconcentПозже,concentавтоматически поддерживает собственный глобальный контекст, чтобы вы могли понятьconcentа такжеreactПриложение представляет собой параллельное отношение, а не вложенное или обернутое отношение, единственное, на что следует обратить внимание, — это рендеринг.reactПеред применением желательноconcentПросто начните это.

cc-struct

Конфигурация отдельного модуля

concentНе требуется, чтобы пользователь конфигурировал определение каждого модуля при запуске, но позволяет пользователю определять определенные компоненты и вызыватьconfigureмодуль конфигурации функций, который значительно улучшит определениеpage modelилиcomponent modelопыт кодирования.

.
|____page
| |____Group
| | |____index.js
| | |____model//定义page model
| |   |____reducer.js //可选
| |   |____index.js
| |   |____computed.js //可选
| |   |____state.js //必包含
| |   |____watch.js //可选
| |   |____init.js //可选
| |
| |____...//各种page组件定义
|
|____App.css
|____index.js
|____utils
| |____...
|____index.css
|____models// 各种业务model的定义
| |____home
| | |____reducer.js
| | |____index.js
| | |____computed.js
| | |____state.js
|
|____components
| |____Nav.js
|
|____router.js
|____logo.png
|____assets
| |____...
|____run-cc.js //启动concent,在入口index.js里第一行就调用
|____App.js
|____index.js //项目入口文件
|____services
| |____...

Вышеприведенная структура организации файла кода взята в качестве примера, компонент страницыGroupсодержит собственныйmodel,существуетmodel/index.jsЗавершите определение модуля дляconcentДействия,

// code in page/Group/model/index.js
import state form './state';
import * as reducer form './reducer';
import * as computed form './computed';
import * as watch form './watch';
import init form './init';
import {configure} from 'concent';

//配置模块到`concent`里,命名为'group'
configure('group', {state, reducer, computed, watch, init});

Прежде чем компонент группы будет представлен внешнему миру, представьте егоmodelпросто хорошо

import './model';

@register('GroupUI', {module:'group'})
export default class extends Component {

}

Такой способ организации кода несет в себе полнуюmodelОпределенныйconcentкомпонентов для npm становится возможным, другим пользователям просто нужно установить егоconcentВ приложении, после установки компонента, вы можете использовать компонент напрямую, даже не используя логику пользовательского интерфейса компонента, просто зарегистрируйте вновь написанный компонент в модуле, переносимом компонентом, и полностью повторно используйте все остальные определения модуля, кроме для пользовательского интерфейса.

клон модуля

Для существующего модуля иногда мы хотим полностью переиспользовать все определения в нем, но среда выполнения полностью изолирована.Если мы используем самый глупый метод, это полностью скопировать весь код под целевой модуль, а затем дать новое имя ., настроен наconcentЭто хорошо, но что, если есть 10, 20 или более компонентов, которые хотят повторно использовать логику, но сохраняют изоляцию во время выполнения? Очевидно, что дублирование нескольких копий кода не сработает.concentпоставкаcloneModuleфункции помогают вам сделать это, на самом делеcloneModuleфункция в самый разstateСоздается глубокая копия, а остальные являются определениями функций, поэтому просто сделайте так, чтобы новый модуль указывал на ссылки на эти функции.

на основеcloneModuleФункции, которые можно вызывать в любое время во время выполнения, и вы даже можете написать фабричную функцию, которая динамически создает и отменяет привязку компонентов к новым модулям!

//makeComp.js
import existingModule from './demoModel';
import { register, cloneModule } from 'concent';

const module_comp_= {};//记录某个模块有没有对应的组件

class Comp extends Component(){
  //......
}

export makeComp(module, CompCcClassName){
  let TargetComp = module_comp_[module];
  if(TargetComp) return TargetComp;

  //先基于已有模块克隆新模块
  cloneModule(module, existingModule);

  //因为module是不能重复的,ccClassName也是不能重复的,
  //所有用户如果没有显式指定ccClassName值的话,可以默认ccClassName等于module值
  const ccClassName = CompCcClassName || module;

  //注册Comp到新模块里
  TargetComp = register(ccClassName, {module})(Comp);
  //缓存起来
  module_comp_[module] = TargetComp;

  return TargetComp;
}

компоненты рабочего процесса

Компонент concent не изменяет волшебным образом компонент реакции, он просто инкапсулирует слой синтаксического сахара в компоненте реакции.Вы все еще должны понимать весь жизненный цикл компонента реакции, иconcentDumbИсходный жизненный цикл умело абстрагируется, прежде чем его можно будет использовать.defineEffect,defineWatch,defineComputedи другие интересные функции, не обращая внимания на жизненный цикл компонентов класса,thisСделайте так, чтобы функциональные компоненты и компоненты класса имели полную эквивалентную функциональность.

cc-process

Сравнение основных решений для управления состоянием

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

vs redux

Давай сначала поговоримredux, этот токreactПервый брат государственного управления в мире.

Невероятный редуктор Redux

написалreduxпользователи , илиredux wrapper(Такие какdva,rematchи т. д.) пользователям, должно быть очень ясноreduxКонвенции:reducerЭто должна быть чистая функция, если состояние изменится, она должна деконструировать оригинал.stateвернуть новыйstate

// fooReducer.js
export default (state, action)=>{
  switch(action.type){
    case 'FETCH_BOOKS':
      return {...state, ...action.payload};
    default:
      return state;
  }
}

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

  • Один из них заключается в том, чтобы поместить логику асинхронного запроса и логику обработки данных после запроса вactionCreatorПосле записи, затем инкапсулируйте данные какpayload,передачаdispatch, Распределите данные по соответствующимreducer.

Этот жанровый код постепенно становитсяreducerдеконструкцияpayloadзатем синтезировать новыеstateИ вернуть операцию, бизнес-логика вся вactionCreatorЗдесь есть серьезный недостаток такого рода, потому что вся бизнес-логикаactionCreatorвнутри,reducerв функцииtypeЗначения все превратились в кучу чего-то вродеCURDметод именования,saveXXModel,updateXXModelXXField,setXXX,deleteXXXИмена, которые, казалось бы, не имеют ничего общего с бизнес-логикой, переполненыreducerфункция, в то время как наш отладчик состояния записываетtypeЗначения - это именно эти методы именования, вы можете увидеть соответствующий процесс перехода в инструменте отладкиtypeСписок, просто получить информацию о том, какие данные были изменены, но понятия не имею, откуда эти состояния распространяютсяpayloadВызвал изменение и даже хотел знать, какое взаимодействие этих представлений пользовательского интерфейса вызвало изменение состояния, вы можете получить это только из кодаreducerизtypeНачните с ключевого слова в качестве условия поиска и ищите другие файлы кода в обратном порядке.

  • Другой - позволитьactionCreatorКак можно тоньше, отправляйте синхронные действия и возвращайтесь напрямую, а асинхронные действия используют функции thunk илиredux-sagaДождитесь обработки сторонней библиотекой и получите данные как можно раньше.actionобъект, отправленный вreducerв функции,

В этом режиме нашаactionCreatorТонкий, делает то, что говорит его название, просто отвечает за созданиеactionобъект, и поскольку наша логика обработки данныхreducerздесь, нашtypeЗначения могут быть названы в соответствии с мотивацией или сценарием вызывающего абонента, например.formatTimestamp,handleNameChanged,handelFetchedBasicDataд., но посколькуreduxИз-за архитектуры ваши действия, инициируемые пользовательским интерфейсом, неизбежно должны пройти два шага, один шаг черезactionCreatorгенерироватьaction, второй шаг проходит черезreducerиметь дело сpayloadСинтезировать новоеstate,такactionCreatorименование иreducerTypeИменование обычно используется для удобства последующего чтения, чтобы иметь возможность получить контекстную информацию, и оно, вероятно, станет одним и тем же именем, напримерfetchProductList,существуетactionCreatorпоявляется один раз, затем вreducerTypeпоявиться снова

редьюсер, который уменьшает сложность до концентрации

КонцентрацияreducerЕго роль состоит в том, чтобы вернуть новое представление фрагмента, так что вы можете думать о нем как оpartialStateGeneratorфункцию, вы можете объявить ее как обычную функцию

//code in fooReducer.js
function fetchProductList(){
}

Это также может быть асинхронная функция или функция-генератор.

async function fetchProductList(){
}

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

function _setProductList(dataList){
  return {dataList};
}

//获取产品列表计基础数据
async function fetchProductBasicData(payload, moduleState, ctx){
  const dataList = await api.fetchProductBasicData();
  return {dataList};//返回数据,触发渲染
  // or ctx.dispatch(_setProductList, dataList);
}

//获取产品列表计统计数据,统计数据较慢,分批拉取 (伪代码)
async function fetchProductStatData(payload, moduleState, ctx){
  const dataList = moduleState.dataList;
  //做分批拉取统计数据的ids,逻辑略...... 
  const batchIdsList = [];
  const len = batchIds.length;

  for(let i=0; i<len; i++){
    const ids = batchIdsList[i];
    const statDataList = await api.fetchProductBasicData(ids);

    //逻辑略...... 游标开始和结束,改变对应的data的统计数据
    let len = statDataList.length;
    for(let j=0; j<len; j++){
      dataList[j+cursor].stat = statDataList[j];//赋值统计数据
    }
    await ctx.dispatch(_setProductList, dataList);//修改dataList数据,触发渲染
  }
}

//一个完整的产品列表既包含基础数据、也包含统计数据,分两次拉取,其中统计数据需要多次分批拉取
async function fetchProductList(payload, moduleState, ctx){
  await ctx.dispatch(fetchProductBasicData);
  await ctx.dispatch(fetchProductStatData);
}

Теперь вам просто нужно вызвать экземпляр представления?dispatchЗапустить обновление

//属于product模块的实例调用
this.$$dispatch('fetchProductList');

//属于其他模块的实例调用
this.$$dispatch('product/fetchProductList');

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

concent делает упор на возврат состояния сегмента, который нужно обновить, а не на синтез нового состояния для возврата.С точки зрения принципа работы, поскольку информация о ключе наблюдения отмечена в классе concent, чем меньше и точнее состояние, представленное редюсером , тем больше это способствует ускорению поиска. Обеспокоены экземплярами этих изменений значения ключа, и конценту разрешено определять ключwatchа такжеcomputedфункция, сведение коммитов к минимуму не приведет к избыточномуwatchа такжеcomputedЛогика функции. С точки зрения бизнеса новое состояние, которое вы возвращаете, должно быть описано именем функции. Когда мы интуитивно интерпретируем функцию, мы обычно знаем, какая обработка была выполнена, и, наконец, возвращаем новое состояние фрагмента для концентрации, которое В соответствии с ^_^ линейного мышления остальная часть логики обновления пользовательского интерфейса остается сосредоточенной.

Читатель мог заметить, чтоreduxА как насчет предлагаемых преимуществ чистых функций, которые легко тестировать и которые не имеют побочных эффектов? Может ли это быть отражено в концентрате?На самом деле об этом можно не беспокоиться, потому что вы можете видеть, есть у функции побочные эффекты или нет, в зависимости от того, как вы объявите функцию, асинхронность (или генератор) является побочным эффектом Функция, в противном случае это чистая функция. Вы можете напрямую вызвать чистую функцию в своем пользовательском интерфейсе или вызвать функцию побочного эффекта. Она определяется в соответствии с вашим сценарием использования. Имя функцииtype, не осталосьactionCreatorМир стал намного тише?

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

function inc(payload, moduleState, ctx){
  ctx.dispatch('bar/recordLog');//这里不使用await,表示异步的去触发bar模块reducer里的recordLog方法
  return {count: moduleState.count +1 };
}

@register('Counter', 'counter')(Counter)
class Counter extends Component{
  render(){
    return <div onClick={()=> this.?invoke(inc}>count: {this.state.count}</div>
  }
}

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

cc-core

Комплексный опыт Redux

несмотря на то чтоreduxОсновной код очень прост, предоставляяcomposeReducers,bindActionCreatorsи другие вспомогательные функции, такие как мостыreactизreact-reduxпоставкаconnectфункция, которая требует разнообразного почеркаmapStateToPropsа такжеmapDispatchToPropsИ другие операции, весь процесс вниз, на самом деле делают код очень раздутым, поэтомуdva,rematchЖдатьredux wrapperУлучшения в этой области были сделаны для упрощения сложности, но независимо от того, как она упакована, снизу вверх, дляreduxДля процесса обновления любойactionРаздача проходит через всеreducer,reducerПройти весь возвращенный статусconnectздесьreducerВсе компоненты, соответствующие состоянию, после раунда неглубокого сравнения (вот почему redux должен возвращать новое состояние с помощью синтаксиса деструктурирования) решают, следует ли обновлять подкомпоненты, которые он обертывает.

const increaseAction = {
  type: 'increase'
};

const mapStateToProps = state => {
  return {value: state.count}
};

const mapDispatchToProps = dispatch => {
  return {
    onIncreaseClick: () => dispatch(increaseAction);
  }
};


const App = connect(
  mapStateToProps,
  mapDispatchToProps
)(Counter);

Простой и прямой практический опыт Concent

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

//Counter里直接可以使用this.$$dispatch('increase')
class Counter extends Component{
  render(){
    return <div onClick={()=> this.$$dispatch('increase')}>count: {this.state.count}</div>
  }
}

const App = register('Counter', 'counter')(Counter);

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

хранитьstateТакже напрямую вводится в это, потому что изsetStateВ начале звонка имеет возможность синхронизировать переход наstoreспособность, введенная таким образом вstateЭто тоже естественная вещь.

Конечно, concent также позволяет пользователямstateдругие не-storeключи, поэтому их значения являются приватными, если пользователю это не нравитсяstateЗагрязненный, не люблю стратегию обратного наследования, тоже самое можно записать как

class Counter extends Component{
  constructor(props, context){
    super(props, context);
    this.props.$$attach(this);
  }
  render(){
    return(
      <div onClick={()=> this.props.$$dispatch('increase')}>
        count: {this.props.$$connectedState.counter.count}
      </div>
    )
  }
}

const App = register('Counter', {connect:{counter:'*'}, isPropsProxy:true} )(Counter);

vs mobx

mobxэто функциональная библиотека реактивного программирования, которая предоставляет библиотеку-мостmobx-reactБудуreactв полностью реактивную модель программирования, потому чтоmobxпреобразует определенное состояние в наблюдаемое, поэтому Пользователям нужно только изменить данные,mobxСоответствующий представление будет обновляться автоматически, поэтому некоторые люди шутилиmobxБудуreactстать похожимvueАвторский опыт, данные автоматически сопоставляются с представлением, и нет необходимости отображать вызовsetState.

По существу, всеmvvmФреймворк полностью посвящен данным и представлениям, и React доводит единый поток данных до крайности,mobxдляreactВнесите исправления в представление автоматического сопоставления данных. Когда дело доходит до автоматического сопоставления, ключевым является автоматический. Как фреймворк воспринимает изменение данных?mobxпринять иvueта же идея, используяpushрежим обнаружения изменений, т.е.getterа такжеsetterДелать перехват, когда пользователь изменяет данные, фреймворк знает, что данные изменились, иreactи наш текущий горячий апплет и т. д.pullрежим для обнаружения изменений, выставитьsetStateа такжеsetDataИнтерфейс предоставляется пользователю, так что пользователь может активно отправлять измененные данные, прежде чем узнает, что данные изменились.

concentпрактически не изменилсяreactрабочий режим, все еще используяpullрежим для обнаружения изменений, единственная разница в том, что пустьpullПроцесс становится более интеллектуальным, когда создается экземпляр пользовательского компонента,concentИзвестна следующая информация:

  • какому модулю принадлежит экземпляр
  • В примере показано, какие ключевые значения этого модуля изменяются
  • Какие еще модули дополнительно подключены к инстансу

При этом ссылка на инстанс будет собрана и сохранена и не будет освобождена до выгрузки.

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

Вам нужна автоматическая картография?

Здесь мы первый вопрос следует выдвинуть, нам действительно нужно автоматически сопоставить его?

Когда приложение становится все больше и больше и модулей становится все больше, прямая модификация данных приводит к множеству неопределенных дополнительных факторов, которые невозможно отследить.vueпри условииvuexдля руководства и стандартизации того, как пользователи изменяют состояние в больших приложениях, в то время какmobxтакже обеспечиваетmobx-state-treeЧтобы ограничить поведение пользователя при изменении данных, с помощью унифицированного обходаactionспособ сделать весь процесс модификации прослеживаемым и отлаживаемым.

Стоимость модернизации

Поэтому в крупномасштабных приложениях мы все надеемся стандартизировать способы изменения данных пользователями, а затемconcentот всего сердцаreactИ отразятся преимущества построения, которые могут быть отsetStateНачните пользоваться преимуществами управления состояниями без необходимости доступа пользователей к дополнительным вспомогательным функциям и большому количеству функций декоратора (для определений на уровне полей), а также с идеальной поддержкой прогрессивного рефакторинга пользователей, элегантной развязки и разделения бизнеса. логика и представление пользовательского интерфейса, написанный код всегда один и тот жеreactКод вкуса.

Эпилог

concentоколоreactОбеспечивает более удобный и интуитивно понятный опыт кодирования, а также добавляет больше возможностей для написания.reactКомпоненты приносят больше удовольствия и пользы, будь то традиционныеclassЖанр, еще только зарождающийсяfunctionЖанр можно найти вconcentНаслаждайтесь унифицированным кодированием.

Опираясь на следующие три основных рабочих принципа концентрации:

  • коллекция цитат
  • Обратите внимание на ключевой тег
  • Трансляция статуса

Основываясь на сборе ссылок и наблюдении за ключевыми тегами, можно получить кеш пути обновления горячей точки.Теоретически, если форма объекта фрагмента, который должен быть обновлен, возвращаемый редюсером, неизменна, все еще существует процесс поиска при запуске рендеринга для в первый раз (хотя это уже очень быстро) тот же вызов редюсера может быть напрямую удален и обновлен в следующих словах, что похоже на кеш горячего кода в v8, но редюсер кеша контекста возвращает отношение между форма данных и ссылка, поэтому приложение может работать все быстрее и быстрее. Особенно применение сотен компонентов и n модулей в одном интерфейсе покажет большие преимущества. Это элемент оптимизации, который делается в следующей версии concent, что принесет пользователям более высокая производительность и лучшая производительность.concentцель, которая всегда преследуется.

пасхальные яйцаAnt Design Pro powered by concent🎉🎉🎉

несмотря на то чтоconcentСтандарт будет иметь свой собственный путь развития, но его гибкая архитектура очень легко интегрируется с существующими проектами.concentдоступ кantd-pro(последняя версия версии js — 2.2.0), бизнес-логика исходного кода не изменена, но внесены следующие модификации, и пройден lint-staged accept:

  • Добавьте скрипт runConcent в каталог src.
  • Все модели заменяются определением в формате concent, т.к. umi автоматически считывает определение папки модели и вставляет его в dva, поэтому все модели, относящиеся к concent, помещаются в папку model-cc.
  • Декораторы слоев компонентов, все используемыеconcentзамененыdva, с небольшими грамматическими изменениями
  • представлятьconcent-plugin-loadingПлагин для автоматической настройкиreducerначальное и конечное состояния функции
  • представлятьreact-router-concent, для подключенияreact-routerа такжеconcent
  • представлятьconcent-middleware-web-devtool(первая доступная версия, относительно зачаточная ^_^), используемая для проверки статусаconcentпроцесс перехода состояния

Обратите внимание, что после запуска проекта вы можете открыть консоль и ввестиsss, посмотреть магазин, войтиcc.dispatchилиcc.reducer.**Инициируйте вызов напрямую, перейдите к другим APIналичие официальной документации на веб-сайтеПросмотр, для получения дополнительных знаний и знаний, пожалуйста, переместитеофициальный сайт antd-pro

как бежать

  • Скачать исходный код
git clone git@github.com:concentjs/antd-pro-concent.git
  • Перейдите в корневой каталог и установите зависимости
npm i
  • Запуск и отладка проекта
npm start

Каталог src по умолчанию находится вconcentверсия исходного кода, для запускаdvaверсия, выполнитьnpm run start:old, переключиться наconcent,воплощать в жизньnpm run start:cc

разное

happy coding, enjoy concent ^_^
приветственная звезда


An out-of-box UI solution for enterprise applications as a React boilerplate.