Как убить всех DIV в Zhihu

React.js
Как убить всех DIV в Zhihu

Добро пожаловать на подпискуДемистификация технологии React

это скучный вопрос

Когда мне задали этот вопрос, моя первая реакция была - мне так скучно 🤷‍♂️

Если подумать, эм~, кажется, что все не так просто 🤔

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

Я задумался. . . . .

Zhihu написан React. React использует JSX для представления иерархии страниц. JSX будет преобразован Babel вReact.createElement.

Когда код запускается, React на самом деле получаетReact.createElement()Возвращаемое значение.

Вот и решение!

Нам просто нужно перезаписатьReact.createElementметод, при встречеtype === 'div',мы будемtypeпревратиться вReact.Fragment, т.е. кладем всеdivузлы становятсяFragment, то его можно удалить с сохранением иерархической связи дереваdivуже?

Давайте начнем! !

Как получить объект React

В этот раз я столкнулся с первой проблемой: Zhihu не выставил React на весь мир (бред, конечно нет 😠), как получить объект React?

К счастью, когда мы используемReact Dev Toolsчас,Dev Toolsвставит глобальные переменные на страницу__REACT_DEVTOOLS_GLOBAL_HOOK__, эта переменная станет ссылкойReactа такжеDev Toolsмост.

один из нихrenderersАтрибут относится к средству визуализации, используемому страницей, которое знакомо нам по веб-странице.React-DOM(На стороне клиента, конечно, этоReact-NativeЛа)

мы нашли способfindFiberByHostInstance

Имя метода действительно появилосьFiberшрифт! !

мы знаем,FiberЭто наименьшая планируемая единица React (не спрашивайте, почему, просто спросите у Amway, я ее написал).Демистификация технологии React)

ЭтоfindFiberByHostInstanceФайл, в котором находится метод, должен иметь определения, связанные с React. Мы щелкаем правой кнопкой мыши, чтобы перейти к файлу, который определяет функцию,

искать в файле.createElement

Конечно же, мы нашли его. Нажмите на точку останова, обновите страницу и попробуйте~

Конечно же, он пришел, и все стало интереснее 😊😊😊

посмотриo.aЧто это, em~~ объект сChildren,createElement. . . . . .

Похоже, это объект React

Спешите сохранить с трудом заработанный объект React в глобале, а также кстати сохранить копию React.createElement.

Теперь отпустите точку останова,window.ReactОн уже указал на React, используемый на домашней странице Zhihu.

Изменить метод React.createElement

мы знаем,React.createElementПервый параметр методаtype(Не спрашивайте почему, спросите другую волну AmwayДемистификация технологии React), мы идем вРеагировать на документациюнайти вReact.FragmentОпределение.

if (typeof Symbol === 'function' && Symbol.for) {
  const symbolFor = Symbol.for;
  REACT_ELEMENT_TYPE = symbolFor('react.element');
  REACT_PORTAL_TYPE = symbolFor('react.portal');
  REACT_FRAGMENT_TYPE = symbolFor('react.fragment');
  REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode');
  REACT_PROFILER_TYPE = symbolFor('react.profiler');
  REACT_PROVIDER_TYPE = symbolFor('react.provider');
  // ...
}

Затем измените глобальную переменную

React.createElement = (type, ...args) => {
    if (type === 'div') {
        type = Symbol.for('react.fragment');
    }
    // originCreateElement才是正经的React.createElement
    return originCreateElement(type, ...args);
}

Давайте Kangkang структуру страницы в это время

ok~~~ полный экран div set div (не нравится лицо), затем мы осторожно нажимаем кнопку «следовать», чтобы активировать любой компонентsetState.

Затем настал момент стать свидетелем чуда. . .

За исключением корневого узла, другиеdivВсе исчезло, и наконец восстановили освежающий интерфейс прошлого (большая ошибка)

Суммировать

Через эту скучную статью мы понимаем:

  1. React пожары каждый разsetStateОбновления повторно обходят все дерево Fiber. (В противном случае он не будет нажимать кнопку для всей страницыdivисчезнувший)
  2. Глубокое применение React.createElement.
  3. Слишком много Чжихуdivохватывать

PS: если вы используете Chrome, код будет сжатformattedЗатем нажмите точку останова, обновите страницу и введите точку останова после того, как браузер зависнет, не сомневайтесь, это ошибка Chrome, на момент版本 81.0.4044.138(正式版本) (64 位)Еще не исправлено, рекомендуется использовать версию разработчика ChromeChrome Canary