资讯专栏INFORMATION COLUMN

CoderPad-基于React全家桶写作/新闻一体综合应用的实践总结

DC_er / 2276人阅读

摘要:基于全家桶写作新闻一体综合应用的实践总结在线地址大家伙儿们,又见面了。参照但不可否认非常符合的思想,都在处理大规模数据时彰显优势。最好的办法是使用部署环境。细致的拆分,解耦性更好,以为单位进行修改时,大大降低误伤率的同时,隔离无关的信息。

?CoderPad-基于React全家桶写作/新闻一体综合应用的实践总结

在线地址

GITHUB

大家伙儿们,又见面了?。 自上次Byemess Todo之后,觉得自身不足还是挺多的,期间又萌生了一些将它重构加上更多新特性的想法,之后技术磨炼一阵再来好好改造它。对于Learn by doing这种事情,一次就会上瘾啊有木有❤️,于是乎本着继续精进练习React技术栈,以及实践更多相关技术的初衷,besides that,自己还想再准备一个小项目来为找工作打底气,于是乎就有了CoderPad。

? WHY IS THIS

在最开始的时候,是想做一个催稿app,又是一个集成的idea:提供分类书单,可以记录阅读情况,然后根据这个情况设定或者后台计算智能推荐:何时去写一篇相关的博客(技术博客),当然写作也是在这个app里完成,然后自动部署至github page。 名字我都想好了,就叫催乎...(知乎er们懂的),奈何这是个大工程啊... 我就造出了这么个只有编辑,阅读的阉割版。 另外关于写完markdown直接部署生成静态博客的app我推荐好基友的Page.qy => ? 无代码建站,基于Node.js,React和Electron,很用心的app,向他学习之,他马上又会写出一个UI逆天美的音乐播放器了,你们可以关注他。

? WHAT IT IS

Markdown: 支持本地缓存,保存/删除/查看/下载,追求极简。

NewsFeed: 集成v2ex,HackerNews-Top Stories, Github-Trending

Music: 暂未施工

?Techniques

老朋友React全家桶: 对于这块,值得一提的是react router v4,相对于v3的巨大改动,extremely make sense. 让route与组件化思想更贴切,有种幻觉:定义子route更加随心所欲了。至于为什么... 请君上手感受。

Immutable: 有一些细微的坑,主要体现在数据类型转化上,immutable会将原生JS数据类型进行包装,如Map,List,在对它们进行提取的时候需要注意是否已经转化为原生JS,否则容易出错。 我的建议就是时刻注意提取的数据是什么类型,结合PropTypes进行参数检测,出错时先console看看,一般很快可以解决。 对于多层对象嵌套的时候,为了保险,手动将被嵌套的对象进行指定类型转化,比如{ list: [] } => { list:Immutable.List([]) },如果要偷懒的话可以直接使用fromJS,但是这个方法渗透性强,会将所有内嵌结构进行转化,在本项目的后期重构里就遇到了子数组遍历出来全是immutable object的情况,需要手动再次转化,很是恶心。 这些缺点在redux文档里也有表述,在具体实践后才能有更直观的理解。 参照: What are the issues with using Immutable.JS?.但不可否认Immutable.js非常符合react的思想,都在处理大规模数据时彰显优势。

Reselect:它用来替代我们手写的state selector, 它的主要思想: state1 + state2 => state3, 缓存先决state,它们如果计算结果是相同的,就使用缓存结果不去改变最终state,同样也是immutable思想。 在结合immutable.js的时候,也是坑啊,还是那个老问题,数据类型,state嵌套越深,越麻烦。 所以,现在明白为什么强调Redux State扁平化了吧?

Redux Saga: Oh my.. 无比亲切,至于原因: 我写过这么一篇文章:From Iterator To Async. Saga致力于解决复杂场景下的异步流程控制,用它来管理action触发,酸爽无比。 毕竟控制异步流程这种成就在JS话题下本身就是爽的不要不要的。 本质是使用generator,对于理解CO库的同学们,掌握saga不在话下。在操作极其频繁的场景下(比如游戏),你会感受到他的威力。 推荐一篇文章: Async operations using redux-saga, 在本项目里我主要用它来控制news数据的拉取,采用axios.

Styled Components: 老朋友,更新了2.0版本,同样配合styled-props,效果拔群。 至于一些宏观上的样式设置,的确不如直接写CSS那么直观。 我采用的方法是,特性按组件写,通性和一些涉及多层级样式都放在wrapper里。 也许多带带使用styled-components并不能发挥出色,配合传统CSS写法,应该可以相得益彰。

?Problem and Solution

ref: 对于ref的感觉一直是又爱又恨,毕竟在react之前,dom操作被我们玩的飞起,而react官方的态度一直是不建议使用。 在这次的项目中,markdown editor处的textarea我便采用了Uncontrolled的形式,使用ref保存dom引用。 初衷是为了对频繁的内容变动进行debounce处理,当编辑暂停时才触发一次内容state更新。 随着组件的增加,在一个嵌套达到3层的modal组件里,需要对textarea的value进行重置操作,好了,这下我得从父组件一层层的把这个ref传进去。 那感觉简直不能再糟.... 一刹那感觉官方文档就像和蔼的老司机,句句肺腑之言啊! 不过在你真的遇到这个坑前,是不会有多深的感受的。 要解决这个恶心的传递,只有采用controlled形式,onChange监听,value直接链接state.

Perf: 作为性能测量的利器,测试结果让我发现styled-components的消耗是可观的,尤其是更新到v2.0版本后。在其他方面,由于本项目里的newsFeed可能会涉及频繁点击切换路径的情况,为了防止无谓的重复渲染,给所有presentational components都设置为PureComponent, 接着在一些只需要更新一次的组件里手写shouldComponentUpdate, 还是强调一点: 必须十分清楚传入的参数,以及其结构,并考虑这个结构是否在生产环境中有变化的可能导致判断失效。 还有个值得注意的问题是react-router-v4里的NavLink检测location渲染当前激活地址的link(activeClassName属性)时,注意组件是否是PureComponent, 如果是,必须在父组件传入location,否则PureComponent的shouldComponentUpdate将会判定参数无变化,从而block掉link的动态渲染。参照: Dealing with Update Blocking

Server Side: 由于是使用leancloud部署,用node环境,为了解决v2ex api的跨域问题,自己写了一套请求转发,但是问题来了: 单页APP里为保证刷新后不出现cannot get等问题,必须写上一条app.get("*", (req, res) => {res.sendFile("index.html的路径")} ), 这就很麻烦了,后来经过请教,用正则过滤了请求转发涉及的路径,就避免了路径全局拦截。但是! 这样刷新后,又会遇到cannot get的问题了。 因为再次刷新时url已经变化,浏览器会去请求这个地址,而后台并没有提供此路径的响应。 最好的办法是使用nginx部署环境。(express难道就没办法? 还是我服务端知识短浅啊...要恶补) 另外一个问题: 生产环境和部署环境下由于使用了不同的请求地址,返回的数据的结构存在微小差异,以本项目为例,请求v2ex topic在生产环境下数据是res.data,而到了部署环境下由于使用了自己设置的请求地址,返回的数据成了res.data[0],找了很久才发现问题,值得注意。

Cancellation: 在newsfeed里频繁切换页面时还有一个问题: 也许下一个页面呈现时,上一个页面中触发的fetch操作还没执行完毕。举个例子: 我进入了v2ex的页面,此时组件拉取新闻信息,接着我几乎不等待便切换至github,此时对于v2ex的拉取还在进行。这就是一种浪费了。 为了解决它,起初我尝试用saga结合react-router-redux里提供的LOCATION_CHANGE action来作为判定取消之前未完成fetch的标志。 测试发现就算我点击的是同一个link,依然会触发LOCATION_CHANGE,(真坑啊,完全不符合直觉好么!?)那么有这么一个场景: 当你进入hackerNews等待数据返回,由于时间较久,你不耐烦的再次点击了hackerNews的Link,Boom~~! LOCATION_CHANGE dispatched. 于是乎你的fetch被取消了...,所以用LOCATION_CHANGE作为判定标志在首次拉取这个场景下是不可行的(论corner case重要性..), 后来想出来的解决办法是在三块新闻组件的componentDidMount的顶部dispatch一个STOP_FETCH action,然后将判定取消的标志改为:STOP_FETCH,算是解决了,可总感觉有点暴力,因为一旦组件变多,将要手动。接下来将继续思考更优雅的解决方案,如果大神们有答案,请告知。

?Gain

最大的收获: 主动找上问题,而不是问题找上你。 不折腾,不踩坑,进步颇微。

当container变多时,直接将container component作为单位,多带带设立目录,然后放置对应的components/styled-components/reducer/action. 这就是按feature组织目录的方法。 细致的拆分,解耦性更好,以container component为单位进行修改时,大大降低误伤率的同时,隔离无关的信息。

大概总结出一个Learn by doing的心路历程:

被未尝试的技术吸引,并且有了下一个project的idea

尝试拆分所需技能,分成组块(裂墙推荐知乎金旭亮老师组块学习论)

漫长的学习过程: 读文档,找样例,写小demo倒腾API。由于组块积累未完全,所以无法对project全面下手,自然会很烦躁,并且踏出了舒适区,接收更多的信息。

组块知识积累完毕,project开始施工: 从最简功能需求开始,不断增加新feature: problem -> google -> resolve.

Project成型,评估,修正,改进,more problem come in.

项目总结。然后享受一下独立完成project的成就感。同时也会深刻理解自己的不足,为自己的技术精进之路指明了方向。

以project为单位,循环以上步骤。

最后的领悟: 我早几年干什么去了... 捶胸泪目ing。

⛳️More Feature?

未来可能会补上的:

白噪音组合播放

番茄钟

音乐部分(哈哈哈偷懒了时间不多了,赶紧找工作。)

作为一名新人,还请大家多多指教。同样无耻的求star,2333。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83415.html

相关文章

  • react全家+koa2实现一个多人博客~

    摘要:不断更新笔记效果有待进一步完善搭建一个基于的多人功能登录注册上传头像发表博文发表留言参考自前端部分以的脚手架搭起的全家桶后端采用开发环境开发环境要求以上目录结构如何运行后端默认配置在中请确保本地端口默认可用发布到目录中默 Full-stack-blog(不断更新笔记) 效果Demo(有待进一步完善)搭建一个基于Koa2的多人blog功能(登录注册上传头像,发表博文,发表留言)参考自ht...

    mdluo 评论0 收藏0
  • [在线+源码]vue全家+Typescript开发一款习惯养成APP

    摘要:基于的版本和编写的模仿原生应用的源码地址欢迎项目演示地址建议直接添加到主屏幕端体验差一些前言为什么做这个项目学习全家桶,很长一段时间在用。作者声称之后增强了对的支持,探究在中的支持情况。 vue-ts-daily 基于Vue.js的2.5.13版本和TypeScript编写的模仿原生应用的WebApp.源码地址 欢迎star 项目演示地址 showImg(https://segment...

    fantix 评论0 收藏0
  • 酷狗音乐- Vue / React 全家两种实现

    摘要:引言两个月前用全家桶实现过一次酷狗音乐,最近又用全家桶重构了下,最终成果和的实现基本一致,放个图手机预览戳版本版本。的行为结构表现分离,很明显,而的分离虽然不是很明显,但实际上也是有的。发送指令,最终会到里合并数据,与中的类似。 引言 两个月前用 Vue 全家桶实现过一次 酷狗音乐,最近又用 React 全家桶重构了下,最终成果和 Vue的实现基本一致,放个图: showImg(htt...

    hot_pot_Leo 评论0 收藏0
  • React Native学习资源全家

    摘要:地址语言中文可能是目前最用心收集的优秀开源项目大全。地址语言中文汇集了各类学习资料工具组件开源资源下载以及相关新闻等,只求精不求全。地址语言中文优秀博客,以及优秀的库列表很多英文资料源自于地址语言中文 本文原创首发于公众号:ReactNative开发圈,转载需注明出处。 showImg(https://segmentfault.com/img/bVX3Nc?w=480&h=260); ...

    oysun 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<