Я наконец отправил тебя на большую фабрику

JavaScript
Я наконец отправил тебя на большую фабрику

Эта статья участвовала в мероприятии Haowen Convocation Order, щелкните, чтобы просмотреть:Двойные заявки на внутреннюю и внешнюю стороны, призовой фонд в 20 000 юаней ждет вас, чтобы бросить вызов!

предисловие

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

Там много технических статей, так что можете смело смотреть.

0. Последняя оргия

"Давай, выпей! Никто не трус!"

После разговора чувства глубоки, а рот притуплен.

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

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

"Босс, иди, выпей. Я многому научился у босса, навыки просто потрясающие!"

Чокните стаканы и сделайте один.

"Я всегда думал, чтоRedisэто те, кто пишетJavaТо, что люди хотят делать, я не ожидал, что босс приведет нас кRedisПолучил это. Теперь вам больше не нужно смотреть на лица этих серверов! Босс, вперед! "

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

«Босс, я отвечаю за настройку. Раньше я умел делать толькоhttp缓存, Блядь懒加载Что. Неожиданно я узнал от босса метод настройки с несколькими размерами. Давай, босс, сопровождай меня, чтобы сделать один. "

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

«Эй, все, послушайте меня, как насчет того, чтобы я рассказал вам о неловком инциденте с боссом?»

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

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

Я начал закрывать лицо, не почетно говорить о таких вещах, да?

«Тогда дело не в этом. Дело в том, что начальник действительно пригласил меня на ужин в тот вечер. Как безжалостно перезванивать по моему коду днем, как скромно приглашать меня на ужин ночью. Босс извинился. мне во время еды,Говорит, что мой код не соответствует стандартам, страницаrenderбольше раз. Например:"

function Com (){
    const [price,setPrice] = useState(0); // 初始化0 第1次
    
    useEffect(()=>{
        // fetch data
        setPrice(10.8); // 拿到真实价格 第2次
    },[price])
    return <div>¥{price}</div>
}

// 应该改成一下风格

Api.fetch().then(
    (props)=>{
        render(React.memo(Com),props)
    }
)

function Com (props){
    const [price,setPrice] = useState(props.price); // 初始化0 第1次
    useEffect(()=>{
       // code 
    },[price])
    return <div>¥{price}</div>
}

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

О, да! Да Чжан сдержался первым, и все вино, которое он выпил, выплеснулось наружу. Я знаю, все оставят меня смущенным на месте 😅. Я до сих пор продолжаю улыбаться, улыбаясь в лицо мрачному миру.

«Эй, вы все подождите, подождите! Что это такое? Иногда видение будет вырезать вам маленькую картинку с тем эффектом матового стекла?Однажды начальник посчитал, что мы используем слишком много графических ресурсов, поэтому заставил нас использовать CSS для написания эффекта матового стекла.Вы говорите, босс не безжалостный человек! "

image.png

<div class="mark"> 老大喜欢手动整的毛玻璃效果</div>
$img: 'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/388f7a44af6b4ea3af893a1fcbfadd71~tplv-k3u1fbpfcp-watermark.image';

body {
    height: 100vh;
    display: flex;
    background-image: url($img);
}

.mark {
    position: relative;
    margin: auto;
    width: 500px;
    height: 400px;
    background-color: rgba(255, 255, 255, 0.5);
    overflow: hidden;
    z-index: 10;
    line-height: 300px;
    text-align: center;
    color: #FFFFFF;
    font-size: 20px;
    
    &::before {
        content: "";
        position: absolute;
        background-position: top;
        filter: blur(8px);
        background-image: url($img);
        background-repeat: no-repeat;
        background-attachment: fixed;
        background-size: cover;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: -1;
    }
}

Ах, эй, эй! Я помню, я не заставлял тебя! Разве мы не обсуждали это вместе?

«О, ребята, вы нормальные по сравнению с моими делами, так что это не очень хорошая сделка?»

Сяобай, которая не умеет говорить, к тому же самая красивая из немногих девушек в нашей группе. Уроженец Шанхая по фамилии Бай очень хорошо одевается. Поэтому с первого дня, когда она присоединилась к нам, к ней пришло много людей, чтобы «намутить». Некоторые приходили к ней с сырой нефтью с работы, а некоторые даже просили ее поболтать с ней, когда они проходили мимо. Даже если она не очень хорошо справляется с этими людьми, каждый день есть люди...

Увы, красота - это справедливость! Не ожидал, что Сяобай тоже будет жаловаться на меня?

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

Внезапно на какое-то время стало очень тихо. Да Чжан поспешно призвал.

«Сяо Бай, давай, говори! Всем любопытно, как ты зол!»

"Результат! Помню, когда я менял свой третий костюм, а это был третий день, начальник вдруг сказал мне, чтобы я вечером пораньше уходил с работы, а не работал все время сверхурочно. Оказывается, начальник думал Я был на крючке!»

"Пфф~!"

Несколько человек, которые еще пили, не выдержали, все обрызгались. А потом улыбнулась...

Да, эти люди такие милые. Я могу вывести такую ​​волну людей, я очень доволен.

1. Делайте что-то хорошо и добивайтесь успеха для группы людей

В конце концов, Да Чжан решил уйти. Это то, что я обсудил с Дачжаном, я рекомендую ему хорошую возможность, и он все еще может получить ее здесь.N+1компенсация. Неожиданно ко мне подошел Сяобай.

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

Сяобай также сказала, что из-за слова «белый» в ее имени ее звали Сяо Сяобай.Сяобай умолял меня 2 дня, об этом надо сказать отдельно. Я не буду проявлять инициативу, чтобы позволить Сяобаю уйти, потому что навыков Сяобая недостаточно, и он не может уйти один, как Да Чжан. Если Сяобай попросит уйти в отставку из-за его собственного бизнеса, я, возможно, не смогу это остановить, но я действительно не могу согласиться с такой пожизненной практикой.

На мой взгляд, уровень компетенции front-end

  1. начальный -- 能正常执行需求,代码书写经验足。
  2. средний -- 能理解常用技术栈的原理,并在代码层面写出性能较好的代码,且能hold住一个项目。
  3. передовой -- 能独挡一面。能及时解决线上响应的问题,并能提供技术解决方案。
  4. старший -- 能单独承担商业解决方案。
  5. эксперт -- 技术上广度要有,还要有深度。管理方面能hold住业务,能搞好团队建设,能提升团队整体实力水平。

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

В конце концов, Сяобай и Сяосяобай предложили мне съесть тарелку кисло-острой лапши и достали меня. Сяо Сяобай, 22 года, работает 2 года. Он окончил престижную школу в возрасте 20 лет и действительно является ученым. В тарелке кисло-острых лапш мне подробно объяснили алгоритм оптимизации.

Нейронная сеть на основе хаотического анализа временных рядовУзнать о?

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

Я пойду, талант! Я вдруг почувствовал, что мой храм стал маленьким. Я хотел порекомендовать Сяо Сяобая команде алгоритмов, но мне отказали. Не отклонена командой алгоритма, но отвергнута Сяо Сяобаем. Сяосяобай сказал, что будет практиковаться со мной полгода, а после практики отправится на большую фабрику.Пусть те, кто когда-то смотрел на нее свысока и думал, что она тарелка, посмотрят на нее свысока..

В ПОРЯДКЕ. Хорошо быть молодым, так что давайте начнем практиковаться. Я бы хотел, чтобы через полгода Сяо Сяобай пришел и дал мне пощечину, чтобы дать пощечину этим людям. Здесь стоит флаг.

Делай хорошо одно дело и достигай группы людей.Это то, что я делал.

2. Первый шаг в обучении — понять принципы React, чтобы хорошо писать код React.

После того, как люди пришли, я сделал свой первый технический анализ. Больше ничего, сначала поймите принцип React Hooks.

  • функциональный компонент выполнить функцию
    • Выполнить функциональный компонентrenderWithHooks
    • ИзменятьReactCurrentDispatcherобъект
  • хуки инициализации
    • пройти черезmountWorkInProgressHookСоздать список хуков
    • пройти черезmountStateинициализироватьuseState
    • пройти черезdispatchActionдля управления обновлением компонентов без сохранения состояния
    • пройти черезmountEffectинициализацияuseEffect
    • пройти черезmountMemoинициализацияuseMemo
    • пройти черезmountRefинициализацияuseRef
  • хуки обновления
    • пройти черезupdateWorkInProgressHookнайти соответствующийhooksвозобновитьhooksсвязанный список
    • пройти черезupdateStateполучить последнююstate
    • пройти черезupdateEffectвозобновитьupdateQueue
    • пройти черезupdateMemoсудитьdeps, получить или обновить кэшированное значение
    • пройти черезupdateПолучатьrefобъект

Возьмите сначала каштан:

import {useState,useEffect,memo} from 'react';

const Com = React.memo(({name})=><div>{name}</div>)

function App(){
    const [ num , setNumber ] = useState(0);
    const [ name , setName ] = useState('小白');
    const handerClick=()=>{
        for(let i=0; i<5;i++ ){
           setTimeout(() => {
                setNumber(num+1)
                console.log(num)
           }, 1000)
        }
    }
    
    useEffect(()=>{
        setName(num % 2 ? '小白' : '小小白')
    },[num])
    return <div>
        <Com name={name}/>
        <button onClick={ handerClick } >{ num }</button>
    </div>
}

Q1: Что происходит, когда вы используете хуки (например, useState)? **

погналиuseStateИсходный код: react/src/ReactHooks.js

export function useState(initialState){
  const dispatcher = resolveDispatcher(); // 1
  return dispatcher.useState(initialState);
}

Ой,useState(initialState)Эквивалентноdispatcher.useState(initialState).dispatcherна китайском это значитдиспетчерзначение. То есть вы звонитеuseStateтолько что уведомилидиспетчерзапланировать реальныйuseState.

Q2: Этодиспетчер dispatcherЧто это?

См. исходный код.

function resolveDispatcher() {
  const dispatcher = ReactCurrentDispatcher.current
  return dispatcher
}

Ой,dispatcherОтReactCurrentDispatcherдавай. Давайте проанализируем это, реагируем на текущий диспетчер (Dispatcher).

То есть сюдаDispatcherЭто уже устроено.

Q3: Когда вызывается функциональный компонент?

То есть, когда вызывается ваш компонент приложения? Архитектуру версии React 16 можно разделить на три слоя:

  • Scheduler(Слой планирования): приоритет задач планирования, задачи с высоким приоритетом сначала входят в координатор
  • Reconciler(Уровень координации): создайте структуру данных Fiber, сравните объекты Fiber, чтобы найти различия, и запишите операции DOM, которые должны выполняться объектами Fiber.
  • Renderer(слой рендеринга): отвечает за рендеринг измененной части на странице

мы знаемrenderСначала компонент создаетFiber 链表. Итак, давайте посмотрим на исходный код координационного слоя:react-reconciler/src/ReactFiberBeginWork.js


renderWithHooks(
    null,                // current Fiber
    workInProgress,      // workInProgress Fiber
    Component,           // 函数组件本身
    props,               // props
    context,             // 上下文
    renderExpirationTime,// 渲染 ExpirationTime
);

……

renderWithHooks(
    current,             // current Fiber
    workInProgress,      // workInProgress Fiber
    Component,           // 函数组件本身
    props,               // props
    context,             // 上下文
    renderExpirationTime,// 渲染 ExpirationTime
);

давайте сначала посмотримrenderWithHooksНекоторые из параметров, с которыми мы наиболее знакомы.Componentсама функция,propsэто информация, которую мы передаем функциональному компоненту,contextПредставляет текущий контекст.

Ну неужели нашComponentтолько что вrenderWithHooksметод называется? Затем посмотрите исходный код (немного упрощенный).


function renderWithHooks(
  current,
  workInProgress,
  Component,
  props,
  secondArg,
  nextRenderExpirationTime,
) {
  renderExpirationTime = nextRenderExpirationTime;
  currentlyRenderingFiber = workInProgress;

  workInProgress.memoizedState = null;
  workInProgress.updateQueue = null;
  workInProgress.expirationTime = NoWork;

  // 3 很重要!
  ReactCurrentDispatcher.current =
      current === null || current.memoizedState === null
        ? HooksDispatcherOnMount
        : HooksDispatcherOnUpdate;

  let children = Component(props, secondArg); // 2

  // code ...

  ReactCurrentDispatcher.current = ContextOnlyDispatcher;

  renderExpirationTime = NoWork;
  currentlyRenderingFiber = null;

  currentHook = null
  workInProgressHook = null;

  didScheduleRenderPhaseUpdate = false;

  return children; // end
}

Ой,renderWithHooksВозвращаемое значение - дети, в то время какchildren = Component(props, secondArg);

Дело решено, наша функциональная составляющая находится вrenderWithHooksпозвонил и в конце концовreturnвозвращение.

Вернемся к 3 снова,ReactCurrentDispatcher.currentРазве это не было ясно объяснено раньше?диспетчердомой? ! Объясните эту строку кода: когдаcurrentзаnullилиcurrentизmemoizedStateсобственностьnullставитьHooksDispatcherOnMountназначенный намдиспетчер, иначе поставитьHooksDispatcherOnUpdateназначенный намдиспетчер.

Из этих двух имен видно, что одноMountДиспетчер, одинUpdateдиспетчер. То есть инициализироватьhooksкогдаMountДиспетчер, пора обновитьUpdateдиспетчер? !

хорошо, дело теперь сломано на 80%.

Q4: Что такое workInProgress и что такое workInProgress.memoizedState?

workInProgress: Судя по названию,ход работыилиработа в процессеты имеешь ввиду? Тогда это объект? У объекта должны быть какие-то атрибуты, описывающие разную информацию, верно?

workInProgress.memoizedState:

  • использоватьuseState,спастиstateИнформация
  • использоватьuseEffect,спастиeffectобъект
  • использоватьuseMemo, спасти缓存的值иdeps
  • использоватьuseRef, спастиrefобъект.

То есть workInProgress.memoizedState хранит информацию об используемых нами хуках.

здесьworkInProgress.updateQueueЯ упомяну об этом позже.

Q5: звонокuseStateчто случилось.

Сначала посмотрите на упрощенный исходный код.

function mountState(
  initialState
){
  const hook = mountWorkInProgressHook();
  
  //如果 initialState为函数,则执行initialState函数。
  if (typeof initialState === 'function') {
    initialState = initialState();
  }
  hook.memoizedState = hook.baseState = initialState;
  const queue = (hook.queue = {
    pending: null,  // 待更新的内容
    dispatch: null, // 调度函数
    lastRenderedReducer: basicStateReducer,
    lastRenderedState: initialState, // 最新一次渲染的 state
  });

// 负责更新的函数
  const dispatch = (queue.dispatch = (dispatchAction.bind( 
    null,
    currentlyRenderingFiber,
    queue,
  )))
  return [hook.memoizedState, dispatch];
}

О, этот код явно легче анализировать.

  1. Сначала получите информацию о ловушке, то естьconst hook = mountWorkInProgressHook();
  2. парный входinitialStateвынести приговор. Тогда будетinitialStateназначить вhook.memoizedStateиhook.baseState
  3. Далее объявляется очередьqueue, см. примечания для информации.
  4. Объявите диспетчерскую функцию dispatch , которая используется для обновления состояния
  5. Возвращает массив, который нам удобно деструктурировать. Это:
const [x,setX] = useState(initialState);

Тогда что такое dispatchAction?

function dispatchAction<S, A>(
  fiber: Fiber,
  queue: UpdateQueue<S, A>,
  action: A,
)

Сравнивая приведенный выше код,Что означает буква S? что означает А?

setXпросто позвониdispatchActionБар? Отображение исходного кодаdispatchActionЕсть ужеcurrentlyRenderingFiber, queueдва параметра, тоsetXВходящий параметр должен быть третьим параметромactionправильно?

Q6: dispatchActionЧто, черт возьми, происходит?

function dispatchAction(fiber, queue, action) {
   // code ...
    
  // step 1 : 初始化要更新的信息
  const update= {
    expirationTime,
    suspenseConfig,
    action,
    eagerReducer: null,
    eagerState: null,
    next: null,
  }
 
  // 判定是不是首次更新
  const pending = queue.pending;
  if (pending === null) {  // 证明第一次更新
    update.next = update;
  } else { // 不是第一次更新
    update.next = pending.next;
    pending.next = update;
  }
  
  queue.pending = update;
  const alternate = fiber.alternate;
  
  // 判断当前是否在渲染阶段 
  if ( fiber === currentlyRenderingFiber || (alternate !== null && alternate === currentlyRenderingFiber)) {
   // code ...
  } else { 

   // code ...
   
   // 剩下的事情交由 调度层 去完成。
    scheduleUpdateOnFiber(fiber, expirationTime);
  }
}

Q7: Что такое волокно? Что такое связанный список Fiber?

Увы, давайте посмотрим на свойства объекта Fiber в целом.

type Fiber = {
  /************************  DOM 实例相关  *****************************/
  
  // 标记不同的组件类型, 值详见 WorkTag
  tag: WorkTag,
  // 组件类型 div、span、组件构造函数
  type: any,
  // 实例对象, 如类组件的实例、原生 dom 实例, 而 function 组件没有实例, 因此该属性是空
  stateNode: any,
 
    /************************  构建 Fiber 树相关  ***************************/
  
  // 指向自己的父级 Fiber 对象
  return: Fiber | null,
  // 指向自己的第一个子级 Fiber 对象
  child: Fiber | null,
  
  // 指向自己的下一个兄弟 iber 对象
  sibling: Fiber | null,
  
  // 在 Fiber 树更新的过程中,每个 Fiber 都会有一个跟其对应的 Fiber
  // 我们称他为 current <==> workInProgress
  // 在渲染完成之后他们会交换位置
  // alternate 指向当前 Fiber 在 workInProgress 树中的对应 Fiber
    alternate: Fiber | null,
        
  /************************  状态数据相关  ********************************/
  
  // 即将更新的 props
  pendingProps: any, 
  // 旧的 props
  memoizedProps: any,
  // 旧的 state
  memoizedState: any,
        
  /************************  副作用相关 ******************************/
  // 该 Fiber 对应的组件产生的状态更新会存放在这个队列里面 
  updateQueue: UpdateQueue<any> | null,
  
  // 用来记录当前 Fiber 要执行的 DOM 操作
  effectTag: SideEffectTag,
  // 存储要执行的 DOM 操作
  firstEffect: Fiber | null,
  
  // 单链表用来快速查找下一个 side effect
  nextEffect: Fiber | null,
  
  // 存储 DOM 操作完后的副租用 比如调用生命周期函数或者钩子函数的调用
  lastEffect: Fiber | null,
  // 任务的过期时间
  expirationTime: ExpirationTime,
  
    // 当前组件及子组件处于何种渲染模式 详见 TypeOfMode
  mode: TypeOfMode,
};

В React 16 вся задача разбита на небольшие задачи для обработки, и каждая маленькая задача относится к построению узла Fiber.

image.png

Что касается связанного списка Fiber.

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

  • 父级节点кто это
  • 子级节点Кто это, чтобы знать его
  • 下一个兄弟节点кто это.

Свойства, прикрепленные к объекту Fiber, подробно перечислены выше.Мне нужно, чтобы ты взглянул.

Когда все объекты DOM Fiber сгенерированы, Fiber, который должен выполнять операции DOM, создаст связанный список Fiber. Что касается принципа построения связанного списка Fiber, следующий код (Это не исходник, просто чтобы было понятнее, я написал волну вручную. Надеюсь, у вас есть время, чтобы написать это вручную):


import React from "react"
const jsx = (
<div id="a">
 <div id="b1">
   <div id="c1">
        <div id="d1"></div>
        <div id="d2">
            <div id="e1"></div>
            <div id="e2"></div>
        </div>
   </div>
   <div id="c2"></div>
 </div>
 <div id="b2"></div>
</div>
)
const container = document.getElementById("root")
/**
* 1. 为每一个节点构建 Fiber 对象
* 2. 构建 Fiber 链表
* 3. 提交 Fiber 链接
*/
// 创建根元素 Fiber 对象
const workInProgressRoot = {
stateNode: container,
  props: {
   children: [jsx]
  }
}
let nextUnitOfWork = workInProgressRoot
function workLoop(deadline) {
  // 如果下一个要构建的执行单元存在并且浏览器有空余时间
  while (nextUnitOfWork && deadline.timeRemaining() > 0) {
   // 构建执行单元并返回新的执行单元
   nextUnitOfWork = performUnitOfWork(nextUnitOfWork)
  }
  // 如果所有的执行单元都已经构建完成
  if (!nextUnitOfWork) {
   // 进入到第二个阶段 执行 DOM 操作
   commitRoot()
  }
}
// Fiber 工作的第一个阶段
function performUnitOfWork(workInProgress) {
  // 构建阶段向下走的过程
  // 1. 创建当前 Fiber 节点的 DOM 对象并存储在 stateNode 属性中
  // 2. 构建子级 Fiber 对象
  beginWork(workInProgress)
  // 如果子级存在
  if (workInProgress.child) {
   // 返回子级 构建子级的子级
   return workInProgress.child
  }
  // 开始构建阶段向上走的过程
  // 如果父级存在
  while (workInProgress) {
   // 构建 Fiber 链表
   completeUnitOfWork(workInProgress)
   // 如果同级存在
   if (workInProgress.sibling) {
     // 返回同级 构建同级的子级
     return workInProgress.sibling
   }
   // 同级不存在 退回父级 看父级是否有同级
   workInProgress = workInProgress.return
  }
}
function beginWork(workInProgress) {
// 如果 Fiber 对象没有存储其对应的 DOM 对象
if (!workInProgress.stateNode) {
 // 创建 DOM 对象并存储在 Fiber 对象中
 workInProgress.stateNode = document.createElement(workInProgress.type)
 // 为 DOM 对象添加属性
 for (let attr in workInProgress.props) {
   if (attr !== "children") {
     workInProgress.stateNode[attr] = workInProgress.props[attr]
   }
 }
}
// 创建子级 Fiber 对象
if (Array.isArray(workInProgress.props.children)) {
 // 记录上一次创建的子级 Fiber 对象
 let previousFiber = null
 // 遍历子级
 workInProgress.props.children.forEach((child, index) => {
   // 创建子级 Fiber 对象
   let childFiber = {
     type: child.type,
     props: child.props,
     return: workInProgress,
     effectTag: "PLACEMENT"
   }
   // 第一个子级挂载到父级的 child 属性中
   if (index === 0) {
     workInProgress.child = childFiber
   } else {
     // 其他子级挂载到自己的上一个兄弟的 sibling 属性中
     previousFiber.sibling = childFiber
   }
   // 更新上一个子级
   previousFiber = childFiber
 })
}
}
function completeUnitOfWork(workInProgress) {
  let returnFiber = workInProgress.return
  if (returnFiber) {
   // 链头上移
   if (!returnFiber.firstEffect) {
     returnFiber.firstEffect = workInProgress.firstEffect
   }
   // lastEffect 上移
   if (!returnFiber.lastEffect) {
     returnFiber.lastEffect = workInProgress.lastEffect
   }
   // 构建链表
   if (workInProgress.effectTag) {
     if (returnFiber.lastEffect) {
       returnFiber.lastEffect.nextEffect = workInProgress
     } else {
       returnFiber.firstEffect = workInProgress
     }
     returnFiber.lastEffect = workInProgress
   }
  }
}
// Fiber 工作的第二阶段
function commitRoot() {
// 获取链表中第一个要执行的 DOM 操作
let currentFiber = workInProgressRoot.firstEffect
// 判断要执行 DOM 操作的 Fiber 对象是否存在
while (currentFiber) {
 // 执行 DOM 操作
 currentFiber.return.stateNode.appendChild(currentFiber.stateNode)
 // 从链表中取出下一个要执行 DOM 操作的 Fiber 对象
 currentFiber = currentFiber.nextEffect
}
}
// 在浏览器空闲的时候开始构建
requestIdleCallback(workLoop)

2. Спустя 1 час после выхода в интернет Сяо Сяобай плакала

Прошло 2 недели с тех пор, как я в последний раз делился чем-то, связанным с React Hooks. Xiaoxiaobai усердно учился, компания работала сверхурочно, чтобы написать требования, и отправилась домой, чтобы продолжить сверхурочную работу над написанием кода.

Я слишком сильно давлю на людей?

Собака залаяла (у меня зазвонил телефон).

"Что с тобой, оперативник сказал, что с онлайном проблемы! Просто обещал тебе кого-то удержать, а ты мне отплатил вот так..."

Снято! Я повесил трубку. Он ничего не сказал, просто повесил трубку. Я быстро вернулся на свое место, а Сяо Сяобай расплакалась и чуть не потеряла сознание на рабочем месте. Должен ли я распылять на этот раз:ММП, если что-то пойдет не так, ты умеешь плакать, если что-то пойдет не так, ты должна сразу мне сказать!

Дело в том, что Xiaoxiaobai сделал страницу активности, содержание которой позволяет пользователям щелкать по экрану, чтобы брать красные конверты. Проблема в том, что пользователь может схватить красный конверт, когда щелкнет по нему.Теоретически, пока скорость руки достаточно высока, экран может распознать жест пользователя, чтобы схватить его. То есть, если вы нажмете 1000 раз, вы сможете получить 1000 красных пакетов. Конечно, это утверждение слишком преувеличено. Пользователи могут получить красный конверт на сумму до 200 юаней, а позже будет получено не более 200 юаней.

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

Разобравшись в общей ситуации, мой телефон был набран неким оперативным начальником.

"Старое железо, как эта проблема?"

«На данный момент поступило несколько десятков жалоб, но ожидается, что в будущем будет много трафика. Сейчас я попросил своих подчиненных приостановить продвижение этой страницы мероприятия. Что вы там делаете?»

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

В телефоне секунд десять тишина. Я знаю, что она мне поможет.

— Ты уверен, что через полчаса все будет хорошо?

"может."

«Если это сделано, иди на свидание со мной».

Снято! Телефон брошен в ящик стола, у Бога особый день, не тревожь меня, когда придет Бог!

Я подошел к Сяо Сяобай, она все еще плакала. Сяобай успокаивал меня и видел, как я иду.

— Босс, что делать?

«Отойди в сторону».

Я сижу на месте Сяобая.

«Пароль блокировки экрана».

"110gaosuwoyaodidiao" (110 сказал мне вести себя сдержанно)

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

«Сяо Бай, могу я тебе доверять?»

"Может."

Я открыл vscode, а в SDK был код для взлома. В основном сделайте несколько вещей:

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

Это опасно. Без тестирования, без проверки. Даже не законно. Но хуже результата, чем сейчас, нет.

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

«Сяо Бай, достань свой телефон».

Я проверил время, прошло 15 минут. В это время Сяо Сяобай перестала плакать, наверное, потому что я испугалась.

«Сяо Сяобай, возьми тестовую машину и запусти ее в течение 5 минут. Ты сможешь это сделать?»

Сяо Сяобай машинально кивнул, а затем побежал за своим телефоном.

Я посмотрел на время на своем телефоне, и через 21 минуту я был в сети. Сяо Сяобай внезапно схватил меня.

«Босс, здесь есть Xiaomi Mi 6, но он все еще немного застрял».

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

После того, как операция завершена, он ждет очереди, чтобы выйти в сеть. — неожиданно спросил я Сяо Бая.

«Сяо Сяобай, могу я доверять тебе на этот раз?»

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

Я подошел к кабинету начальника и постучал в дверь. Босс бросил стакан с водой в дверь.

«Теперь ты классный! Не принимай меня всерьез! Начальник операции перевел дело на сторону бизнеса, и проблема поднялась до генерального директора (CEO). Что ты скрываешь? Мы решим ее, как только насколько это возможно. Вы знаете, в чем проблема?»

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

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

— Босс, что случилось?

«Люди под тобой вышли из строя, о чем ты меня спрашиваешь?!»

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

«Эй, в чем дело? Я сейчас занят делами».

— Что-то не так?

«Что-то пошло не так? А ты? Мои дела идут нормально, и я не слышал, чтобы кто-нибудь говорил о проблеме».

«Хорошо. Тогда ты будешь занят первым».

Я повесил трубку и посмотрел на босса озадаченными глазами: «Босс, кажется, сегодня запустили новую страницу активности, обманом заставляя пользователей хватать красные конверты».

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

"Босс, разве это не хорошо?"

Затем я сделал вид, что снова звоню Сяо Сяобаю.

«Эй, ты сделал сегодняшнюю страницу активности? Принеси сюда мобильные телефоны. Я здесь, в кабинете директора».

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

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

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

«Боитесь? Пошли, люди, у которых сегодня есть потребности в Интернете, вместе перекусим поздно вечером».

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

«Успокойтесь, когда что-то пойдет не так, хорошо, что меня уволили. Не прошло и дня, как директор увидел, что я не радую глаз, поэтому я осмелился дать ему пощечину!Каждый должен иметь не только умение писать код, но и, что более важно, умение решать проблемы …”

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

3. Сяо Сяобай заинтересован в оптимизации производительности

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

Давайте проанализируем это. Феномен Caton обычно можно обнаружить с помощью отзывов пользователей или мониторинга производительности. Например, мы получили жалобу от пользователя, что активная карточка страницы не может захватить красный конверт, а затем, проверив индикатор зависания на платформе производительности, мы обнаружили, что страница появлялась в течение 10 последовательных кадров более 40 мс, что это серьезное замораживание.

Как с этим бороться?

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

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

Возьмите эту страницу активности (дождь в красном конверте) в качестве примера, пользователь пожаловался, что она зависла, что является интуитивным ощущением, и высокая вероятность связана с эффектом анимации. Существует много видов анимации, но в основном расчеты CSS.

浏览器的主线程В основном отвечает за运行 JavaScript,计算 CSS 样式,元素布局, синтетическая нить в основном отвечает за绘制UI. когдаwidth、height、margin、paddingподождите, покаtransitionКогда значение анимировано, основной поток подвергается стрессу, потому что计算 CSS 样式Это также отнимает много времени. как пользоватьсяtransformвместо того, чтобы установить его напрямуюmargin、padding.

Возьмите каштан. Добавьте элемент DOM, представляющий красный конверт.margin-left: 0px, последний красный конверт находится вmargin-left: 100pxПри нажатии, если в этом процессе шаг = 1, то от 0 до 100, основной поток браузера нужно просчитать 100 раз.После каждого расчета составной поток отрисовывается на GPU и затем рендерится на экран . В этом процессе можно представить себе нагрузку на браузер.

Но если вы используетеtranform:translate(-100px,0), основной поток браузера вычисляет 1 раз, а поток синтеза может отрисовывать 0 сразу до 100. Разницу можно представить.

С другой стороны, это вычислительно трудоемкие операции.

  • Virtual DOMПоявление должно решить проблему задержки производительности, вызванную частыми манипуляциями с DOM. Если вы хотите работать100个DOM, затем сначала сохраните информацию об операцииVirtual DOMВключите, подождите, пока все операции будут завершены, а затем говоритеVirtual DOMОдноразовые обновления реального DOM.React 和 Vue走的不正式 Virtual DOM 路线吗?

  • js расчет. Например, есть большое и малое количество красных конвертов. JS — это один поток, и он уже отвечает на действия пользователя. Если вы хотите, чтобы JS вычислял в это время, вы можете позволить JS сначала вычислить сумму только в один поток и на время отложить в сторону поведение пользователя. Вы сказали, что у пользователей будут призраки, если они не чувствуют себя застрявшими. Есть два решения этой проблемы.

    • Отложите расчет js и подождите, пока все задачи с высоким приоритетом будут выполнены, прежде чем выполнять расчет js.
    • Если вам необходимо вычислить результат во времени, попробуйте вычислить его во время простоя браузера.

Вот момент знания, чтобы упомянуть.

Страница рисуется кадр за кадром. Когда число кадров в секунду достигает 60, страница становится гладкой. Когда оно меньше этого значения, пользователь чувствует себя застрявшим.

1с 60 кадров, на каждый кадр выделяется время 1000/60 ≈ 16 мс, если время выполнения каждого кадра меньше 16мс, значит у браузера есть свободное время.

Если задача не будет завершена в оставшееся время, выполнение задачи будет остановлено, и основная задача продолжит выполняться первой, то естьrequestIdleCallbackВсегда используйте свободное время вашего браузера для выполнения задач.

Один выходной, 11 утра. Я все еще спал (слишком устал), когда позвонил Сяо Сяобай.

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

Снято! Я выбросил телефон. Телефону не потребовалось много времени, чтобы запустить смертельный режим последовательного вызова. Ну, я проиграл, я был неправ, я поднял его...

"Эй, лучше дай мне повод не распылять тебя. Иначе заблокируй!"

"&%@!¥%*(·"

"говорить на английском!"

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

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

«Лао Ти, я зову тебя Лао Ти, ты будешь встречаться с Лао Ти?»

«Даже если вы не встречаетесь, неужели так сложно поесть?»

Внезапно с другого конца телефона раздалось очень серьезное предложение. Я чувствую, что что-то не так.

"Я скоро выйду, не могли бы вы угостить меня едой? Можете ли вы найти время для еды?"

Я поспешно повесил трубку, и группа WeChat взорвалась. Организационная структура была скорректирована, начальник операции повышен до вице-президента, а ветеран операции ушел. Внезапно я потерял сон, и мне пришла в голову еще одна безумная идея.

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

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

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

Как и согласился Сяо Сяобай, подождите полгода. Итак, я начал путь сумасшедшего обмена технологиями.

4. Резюме по оптимизации производительности внешнего интерфейса

На самом деле, самый важный показатель производительности интерфейса — это ««Еще слишком рано выбирать снова»作弊或者欺诈"с методом.

аспект:

  • запросить ресурс

    Статические ресурсы, такие как Html, js, css и изображения, в основном получаются с сервера. Но серверу нужно время, чтобы ответить на запрос клиента, и чем больше объем возвращаемого ресурса, тем больше времени это займет. Итак, если вы хотите быть быстрым, необходимо учитывать три аспекта.

    1. Уменьшите размер ресурса.
      • оптимизацияwebpackБэйл,treeShaking,codeSplit等, постарайтесь, чтобы упакованный объем не был слишком большим.
      • Больше, больше картинок и других ресурсовCDN, что также замаскировано уменьшает объем упаковки. прямо упоминается в кодеCDNссылка на.
    2. Приоритет загрузки ресурсов
      • Например, на первом экране сначала необходимо отрендерить только содержимое видимой области, а также можно выполнить некритическую отложенную загрузку.
      • ключевые данные позволяютnativeСделайте предварительный запрос, а затем передайте данные ключа напрямую в h5
    3. тайник
      • http缓存
      • 本地缓存。Например, собственные ресурсы кэширования изображений
      • 接口缓存。
  • Способ загрузки

    1. ленивая загрузка
      • 骨架屏Узнать о.
    2. Предварительная загрузка
      • NSRУзнать о.
    3. загрузка кеша
      • CSRУзнать о
    4. автономный пакет
  • оптимизация веб-просмотра

    1. 并行初始化
      • Так называемая параллельная инициализация означает, что пользователь входит вApp, система создаетWebViewи загрузите шаблон следующим образомWebView 初始化Это можно делать параллельно с запуском приложения, что значительно сокращает время ожидания пользователя.
    2. 资源预加载. Предварительная загрузка ресурсов относится к предварительному размещению списка статических ресурсов в инициализированном WebView.При последующей загрузке, поскольку эта часть ресурса сильно кэшируется, скорость отображения страницы будет выше. Затем статические ресурсы для предварительной загрузки обычно можно разместить:
      • Внешние ссылки, которые остаются неизменными в течение определенного периода времени;
      • Некоторые базовые фреймворки, JS для многоцелевой адаптации (например, adapter.js), SDK для статистики производительности или сторонние библиотеки (такие как react/vue.js);
      • CSS для базового макета, например base.css.
    3. разное. Как native предоставляет API для запросов интерфейса, который также можно оптимизировать для запросов интерфейса.

    ps: не стоит недооценивать веб-просмотр, он может сократить время на 100-200 мс для вас.

Резюме

  1. Оптимизация решения для этапа запуска приложения

    • оптимизация веб-просмотра
  2. Схема оптимизации для этапа белого экрана страницы

    • Автономный дизайн, например автономные пакеты
    • Скелетонный экран
    • SSR
    • NSR
  3. Схема оптимизации для первого этапа рендеринга экрана

    • Оптимизировать количество запросов
    • Предварительная загрузка интерфейса
  4. Оптимизация производительности DOM

    • Оптимизация длинного списка.memo、usememo
    • уменьшатьRenderчастота
    • js оптимизация расчета
  5. платформа производительности

    Для получения дополнительной информации см. другую историю

5. Время грядущее

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

Да, почти пол года. Скорость роста Сяо Сяобая такая же, как у ракеты. Я серьезно посмотрел на эту группу милых маленьких друзей и обнаружил, что каждый может начать быть сам по себе, и они могут поладить, даже если я уйду.

Я тайно добавил Xiaoxiaobai в друзья, используя другую учетную запись WeChat, и устроил жаркую драку с Xiaoxiaobai во имя того, чтобы помочь ей проникнуть внутрь. Увы, как и ожидалось, молодость легко обмануть.

Сначала я запросил резюме Сяо Сяобая, дал несколько предложений и помог его переработать.

На самом деле, самое чистое резюме — это гарантировать, что HR и интервьюеры смогут быстро сопоставить ваше резюме. Таким образом, не будет недопонимания и траты времени обеих сторон. Например, некоторые люди в резюме любят писать все технологии, которые они знают, например, знают node.js, в результате интервьюер спрашивает о Node, и результат можно себе представить.

Мне нравится иметь биографическую информацию в моем резюме.

个人履历 !== 工作经历。

Резюме — это скорее отражение содержания вашей прошлой работы.述职. Возьмите каштан:

1. 负责toB/toC业务相关项目设计
2. 对ToB、ToC业务的前端开发和管理,把控项目进度,推进合作方达成目标有丰富经验。
3. 喜欢研究新的技术,对能提高项目性能的极其热衷,并致力于将其更新至线上产品。

опыт работы

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

Опыт проекта

Пожалуйста, пишите по следующему шаблону

  1. название проекта
  2. ваша роль в этом проекте
  3. Кратко и по делу расскажите о предыстории проекта
  4. что ты заплатил
  5. 效果/结果 是什么: Например, что вы сделали, чтобы повысить коэффициент конверсии размещенных заказов, сколько денег вы заработали и сколько KPI выполнили. Надеюсь ослепить цифрами.

Самооценка

Я надеюсь, что ваша самооценка напрямую выявит в вас лучшее.

Например;

  1. Практический опыт с ХХХ
  2. Изучите исходный код Vue
  3. Хорошо разбирается в инфраструктуре проекта
  4. ...

не хочу видеть精通、熟悉、了解и т.д. слова. Потому что в глазах тысячи людей тысяча Гамлетов,Может быть, ваше мастерство заключается в фамильярности интервьюера?Лучше объяснить, сколько технических исследований у вас есть по этому поводу.

конец, напишите в конце

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

Но это уже не важно, результат хороший, и после окончания песни все в безопасности.

До свидания, белочка.

До свидания, сволочь.

Xiaoxiaobai, наконец, позвонил и обрызгал меня, что заставило меня сделать такой подход «собачьего лизания». Даже если правда раскрывается, он все равно бьет до смерти и отказывается в этом признаться😂😂😂.

(Желаю тебе удачи, Джунан. Надеюсь, эта длинная история поможет тебе в саморазвитии! Кроме того, детали, которые неясно объяснены в этой статье, могут быть в следующей статье.)