redux必须要配合immutable使用吗?真实感受
日期:2019-11-13
来源:程序思维浏览:1782次
我是一名具有八年工作经验的前端开发人员,目前在一个大型软件企业中工作,以基于React框架和Redux库创建一个新的单页程序。
创建一个空前绝后的网站对所有开发人员都有令人兴奋的前景。我们会天真地眨着大眼睛,抓住新技术,将它们全部放在平台服务器上,然后抽离,对自己那领先时代的天赋惊叹不已。
选定的技术之一是Facebook的Immutable.js。从建立面向功能的编程模型开始,我们将使用该库来实现数据表示并增强数据的不变性。
Immutable和Redux库
不变数据是函数式编程的核心概念,该概念在JavaScript中的应用越来越占主导地位。当使用React框架和Redux库时,不可变数据可以帮助巩固两者的核心原理:如果应用程序状态不变,则网页的文档对象模型(DOM)不变。
许多文章都介绍了使用不可变数据的优点,包括:
- 简化整个程序的数据流
- 不再需要数据复制的防御机制
- 优化数据变化的检测
- 通过记忆改善程序性能
Immutable库
不可变库是Facebook的开源软件库。我们使用redux-immutable模块将该库集成到我们的程序中,以便我们可以使用Immutable库提供的数据类型存储应用程序状态。
要将应用程序状态呈现到网页,我们必须将状态数据从Redux存储传输到React组件。这是通过react-redux模块的“ connect()”修饰符完成的。
在程序的开发过程中,我们注意到了以下优点和缺点。
[优点]加强不变性
无论选择哪个库,使用不可变数据类型的第一个原因是要确保执行项目的人员不会违反不可变的原则。
严格来说,不可变库有助于简化开发过程,因为您不再需要跟踪代码中的数据来查找数据更改的位置。可以始终准确地表示存储在当前存储对象中的程序状态(应用程序状态),而不是不可变的数据类型。有了这个库,我们可以利用上述不可变的数据类型,似乎没有错。但是,确实存在这些缺点,并且这些缺点在开发工作正式开始时就已暴露出来。
[缺点]文档和调试
Facebook为前端开发人员提供的不仅仅是软件框架,而是整个程序的软件生态系统。但是,与React之类的框架相比,Immutable库的文档非常不完整。
如果开发人员不了解Immutable库语法,或者代码无法按预期工作,但通常却无法正常工作,他们将转向文档。为什么代码错误?由于我仍然不了解它,所以每个人都将使用终端日志console.log()大法。不幸的是,当您使用日志查看数据时,会发现您一直在浏览自定义数据类型的属性。
终端日志打印的不可变库对象
要解决此问题,您可以在Immutable库的任何对象上调用toJS()函数,将该对象转换为纯JavaScript对象,然后将其打印出来。但是,这些小问题可能会减慢开发过程,并且如果可以改进文档,情况将会更好。
无论如何,如果您只想确定当前数据,则必须查看文档并进行调试,这实际上并不是生产过程的基础。
[缺点]有反模式化的酸腐气息
通过使用connect()修饰符从程序的存储对象中检索数据,我们可以访问Immutable库的数据对象。但是我们的团队曾经使用本地数据类型编写组件。为了转换数据,我们开发了一种模式,该模式在connect()修饰符中使用toJS()函数,如下所示:
//从存储对象(存储区)获取数据
[@connect](http://twitter.com/connect"Twitter profile for @connect")((state)=>{
// 将存储对象(store)数据转换成原生JavaScript对象
user:state.get(”user“).toJS(),
wine:state.getIn([”drinks“,”wines“]).toJS()
})
classHelloWineextendsComponent{
render(){
// 用ES6版本格式把属性(props)里的数据解构出来
const{user,wines:{houseRed}}=this.props
return{`Hi${user}! Fancy some${houseRed}?`}
}
}
此模式似乎方便且安全,但是在移动设备上使用时,我们发现启动Redux的操作太慢。下面是在Samsung S5上打开程序侧菜单时记录的JavaScript性能的快照。
低效的渲染分析
打开菜单花费了超过2秒钟的时间,这对于采用尖端技术制作的网站程序来说并不理想!
我们跟踪了程序,发现上面编写的模式是问题所在。后台发生的事情是Redux将操作对象发送到存储对象,然后使用reducer()函数生成的新状态更新存储对象。
在用connect()函数修饰组件之后,它将每次检查是否更新了数据。数据已更新,组件将在React生命周期中触发重新渲染。这允许Redux库选择性地渲染React框架组件以提高性能。
每次您运行connect()函数时,应用程序状态都会由toJS()函数转换为本地JavaScript对象,该函数每次都会生成一个新对象。因此,与之前的状态相比,即使当前的不可变库对象不变,结果对象仍然不同。换句话说,当启动任何动作时,将重新渲染用connect()函数修饰的每个动作和元素。
如果您什么都不记得了,那就记住:永远不要在connect()修饰符中调用toJS()函数。
[缺点]与ES6版本的格式不太一致
如果应用程序状态存储在不可变库数据类型中,那么我们的组件也应该使用相同的数据类型,仅此而已。因此我们按原样重组了代码,但它产生了一个很大的缺陷,即缺少本机功能。
例如,ES6的解构功能现在变成了几个get()函数和getIn()函数调用的组合。
const{wines:{houseRed:{name,year}}}=this.props
// 变成
const{wines}=this.props
constname=wines.getIn([”houseRed“,”name“])
constyear=wines.getIn([”houseRed“,”year“])
代码已经更长了,不是那么漂亮。就我个人而言,我不喜欢使用太多的字符串,因为如果我输入错误的单词,程序将抛出JavaScript错误,使我想起错误,现在我只能得到未定义的信息,而真正的问题可能是找不到。
此外,ES6版本的扩展语法也丢失了,这使得该属性的重新分配非常冗长。
这些不可变库语法的缺点使我们感到痛苦,并让我想起了为什么我开始转换模式。如果核心数据类型能够解决问题,那么即使是小问题也可能令人沮丧,并浪费更多宝贵的开发时间。
结果
为了使用Immutable库,我们重新组织了一些组件的代码。然后,我们重新评估了目前的情况并讨论了上述方面。结论是不可变库的唯一好处是它可以增强不可变性,但是有什么意义呢?面向函数编程的真正含义是,您不应尝试修改状态,因此状态的特定数据类型不是技术问题,并且与该想法无关。
在使用Immutable库的过程中,我们考虑了所有缺点,并最终决定将其从项目中完全删除。只要我们遵循函数式编程的原则,我们就有信心处理自己的数据。我们对开发人员的信任,以及彼此之间的代码审查,足以确保不会犯任何低级错误。
- 上一篇:axios拦截器实际应用场景
- 下一篇:Nuxt服务端渲染,采坑之路经验分享!
精品好课