react为何移除mixin,本文主要介绍minix的弊端。
mixin引入了隐式依赖关系
有时候组件依赖于mixin中定义的某个方法,比如getClassName()。有时情况正好相反,mixin会在组件上调用renderHeader()之类的方法。JavaScript是一种动态语言,因此很难强制或记录这些依赖关系。
mixin打破了通常安全的假设,即可以通过搜索组件文件中出现的状态键或方法来重命名它们。你可能会编写一个有状态组件,然后你的同事可能会添加一个读取此状态的mixin。几个月后,你可能希望将该状态移动到父组件,以便与兄弟组件共享。你会记得更新mixin来读取一个道具吗?如果现在其他组件也使用这个mixin呢?
这些隐式依赖使得新团队成员很难贡献代码基。组件的render()方法可能引用类中没有定义的一些方法。移动安全吗?也许它是在mixin中定义的。但是他们中的哪一个呢?你需要向上滚动到mixin列表,打开每个文件,并查找此方法。更糟糕的是,mixin可以指定它们自己的mixin,因此搜索可能会很深入。
通常,mixin依赖于其他mixin,去掉其中一个会破坏另一个。在这种情况下,很难判断数据是如何进出mixin的,以及它们的依赖关系图是什么样子的。与组件不同,mixin不形成层次结构:它们被扁平化并在同一个命名空间中操作。
mixin导致名称冲突
- 不能保证两个特定的mixin可以一起使用。例如,如果FluxListenerMixin定义的handleChange()和WindowSizeMixin定义的handleChange(),就不能同时使用它们。也不能在自己的组件上定义具有此名称的方法。
- 如果你控制mixin代码,那就没什么大不了的。当发生冲突时,可以在一个mixin上重命名该方法。然而,这很棘手,因为一些组件或其他mixin可能已经直接调用了这个方法,你还需要查找和修复这些调用。
- 如果名称与来自第三方包的mixin存在冲突,则不能仅重命名其中的方法。相反,你必须在组件上使用笨拙的方法名称,以避免冲突。
- 对于mixin作者来说,情况也好不到哪里去。甚至向mixin中添加新方法也可能是一种潜在的破坏性改变,因为使用它的某些组件上可能已经存在同名的方法,或者直接使用,或者通过另一个mixin使用。一旦写入,mixin就很难删除或更改。糟糕的想法不会被重构,因为重构太冒险了。
mixin会造成滚雪球般的复杂性
- 即使mixin一开始很简单,随着时间的推移,它们也会变得很复杂。下面的示例基于我在代码库中看到的一个真实场景。
- 一个组件需要一些状态来跟踪鼠标悬停。为了保持逻辑可重用性,可以将handleMouseEnter()、handleMouseLeave()和isHovering()提取到HoverMixin中。接下来,需要有人实现一个工具提示。他们不想在hovermixinn中复制逻辑,所以他们创建了一个使用HoverMixin的工具tipmixinn。tooltipmixinread isHovering()由HoverMixinin其componentDidUpdate()提供,并显示或隐藏工具提示。
- 几个月后,有人想让工具提示方向可配置。为了避免代码重复,他们向TooltipMixin添加了一个新的可选方法getTooltipOptions()的支持。这时,显示弹窗的组件也使用了HoverMixin。然而弹窗需要不同的悬停延迟。为了解决这个问题,有人添加了对可选getHoverOptions()方法的支持,并在TooltipMixin中实现了它。这些mixin现在是紧密耦合的。
- 这很好,但没有新的需求。然而,这种解决方案不能很好地进行扩展。如果你想支持在单个组件中显示多个工具提示怎么办?在组件中不能两次定义相同的mixin。如果工具提示需要在导游的引导下自动显示,而不是在悬停时显示,该怎么办?祝你好运,解耦工具tipmixin与HoverMixin。如果你需要支持悬停区域和工具提示锚点位于不同组件中的情况,该怎么办?你不能轻易地将mixin使用的状态提升到父组件中。与组件不同的是,mixin不会自然而然地进行这些更改。
- 每一个新的需求都使得mixin更加难以理解。使用相同mixin的组件越来越多地与时间耦合在一起。任何新的功能都会被添加到使用mixin的所有组件中。如果不复制代码或在mixin之间引入更多依赖关系和间接关系,就无法分割mixin的“更简单”部分。渐渐地,封装的边界被侵蚀了,由于很难更改或删除现有的mixin,它们变得越来越抽象,直到没有人理解它们是如何工作的。
小结:在react中,使用mixin来实现部分代码的复用,弊大于利,在实践中遭遇的问题普遍竟然是由Mixin引起的,我们可以通过高阶组件来实现交叉部分的问题 ,关于如何使用高阶组件,请看博文 深入理解react高阶组件+代码小例。