专栏首页魔术师卡颂一次性清除“知乎”所有DIV

一次性清除“知乎”所有DIV

学习本文的前置知识:

  • React每次更新都会从rootFiber(根Fiber节点)向下深度优先遍历
  • JSX在编译时会变为React.createElement,在组件render时会调用该方法。

30秒速答:

知乎首页是React写的,我们可以覆写React.createElement方法,在运行时将所有div节点渲染为React.Fragment

这样就能清除所有div

让我们来愉快的改造知乎吧。

拿到React对象

这时候遇到了第一个问题:知乎没把React暴露到全局(废话,当然不会),怎么获取React对象呢?

好在当我们使用React Dev Tools时,Dev Tools会向页面注入全局变量__REACT_DEVTOOLS_GLOBAL_HOOK__

这个变量是连接ReactDev Tools的桥梁。

其中renderers属性指页面使用的渲染器

React源码架构划分为调度器 - 协调器 - 渲染器

对于不同的宿主环境,使用不同的渲染器

  • 对于web,使用ReactDOM渲染器
  • 对于客户端,使用React-Native渲染器

renderers属性中,我们发现一个方法findFiberByHostInstance

方法名居然出现了Fiber字样。

Fiber节点React的最小可调度单元,可以理解为虚拟DOM节点

findFiberByHostInstance方法所在文件一定有React相关定义。我们右键跳转到定义函数的文件,

在文件内搜.createElement

果然让我们找到了。打上断点,刷新页面试试

果然进来了,事情越发有趣了。

看看o.a包含的属性,ChildrencreateElement......

看来这就是React对象了。

我们将来之不易的React对象保存在window,顺便把React.createElement也保存一份。

现在放开断点,window.React已经指向知乎首页内部使用的React啦。

修改React.createElement

React.createElement方法第一个参数为type

在源码中,我们找到React.Fragment对应的type

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');
  // ...
}

接下来,修改全局变量,将所有div变为Fragment

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

让我们滚动页面,触发随便啥组件的setState

接下来,就是见证奇迹的时刻。。。

div都消失啦,终于恢复了往日的清爽界面(大误)

理论上我们可以用这个方法将任何React应用改造成任何样子。

真是,太无聊了......

本文分享自微信公众号 - 魔术师卡颂(gh_bc4b6cbdf9ad),作者:卡颂

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • React 17.0.0-rc.2带来全新的JSX转换

    北京时间 9 月 23 日凌晨,React 团队发布了关于全新 JSX 转换的博客,同时发布了 React 17.0.0-rc.2 版本,新的 JSX 转换不再...

    公众号@魔术师卡颂
  • isObject

    公众号@魔术师卡颂
  • 代数效应与React

    React核心团队成员Sebastian Markbåge[1](React Hooks的发明者)曾说:我们在React中做的就是践行代数效应(Algebrai...

    公众号@魔术师卡颂
  • React Component vs React Element

    有答“组件声明”的,有答“组件调用的”,有“组件初始化”的,还有“使用一个组件”的。没有一个统一的称呼。造成这样局面的原因是很多时候我们都没有去详细的了解过JS...

    前端博客 : alili.tech
  • React 引领未来的用户界面开发框架 - 思维导图

    梁源
  • React从入门到精通系列之(21)React顶级API

    全局变量React是React库的入口。如果你通过一个script标签使用的React,那么它的顶级API都会在全局环境下一个名称为React的变量上。如果你是...

    前端博客 : alili.tech
  • 为什么要选择React

    无意比较几大框架的优劣,但是要入手一门框架,对于刚学习的同学而言,学谁的价值最高?是一个绕不开的问题。

    用户6901603
  • 2020 年你应该知道的 React 库

    React 已经诞生很久了,自从它诞生开始,围绕组件驱动形成了一个非常全面的生态,但是来自其他编程语言或者框架的开发人员很难找到要构建一个 React 系统的所...

    桃翁
  • React 17 RC 版发布:无新特性,却有新期待!

    React 17 版本很特别,因为它并没有任何面向开发者的新功能,而是专注在了如何更轻松地升级 React 本身。

    zz_jesse
  • 21个让React 开发更高效更有趣的工具

    有没有想过你的应用程序的哪些包或哪部分代码所占总大小的多少? Webpack Bundle Analyzer可以帮助咱们分析。

    Javanx

扫码关注云+社区

领取腾讯云代金券