背景
学习一门前端框架,不动手是不行的。所以当我学习react有一段时间时,就打算开始写一个react的个人项目,前后端一起写的话,比较耗时间,所以就选了提供了优质api的Cnode社区,感谢。(如果我参与的合作项目,产品选的技术栈是react的话,我也不用自己写个app了,Orz)
希望各位大爷给个star勒,就右上角轻轻一点,比心
传送门:源码地址
Demo
过程
分析需求
需求是做一个社区的webapp,首先一个社区的功能,就有 登录注册(这次没有注册), 自己的信息, 发帖, 查看别人的发帖, 查看别人的主页,评论他人的帖子等等等。功能太多,我们开发时总不能这部分做点,那部分做点。我们得将这些功能变成一个一个可拆解的模块,比如下图便是我的分块,
现在分块出了个雏形,那么就有的放矢了。我们开发时,可以先从某一个块开始动手。比如可以先从登录这一块开始,每个独立的模块开发完成后,可以进行连接,其实主要是路由的转跳。完成后,可以进行调试,看看整个跑起来感觉如何(我只在我的安卓机调试了一遍)。
选型
其实做webapp, 我更喜欢用Vue, 但是一开始我的目的就是打算用react的技术栈进行一次实战。react,redux, react-redux这三样是跑不掉的,虽然我一开始是想用dva,但是我看了一遍,觉得还是用前者好了,原因不是dva不好,个人项目还是看我个人的学习目的而选择的。不过从dva中看到的一个redux处理异步action的中间件,redux-saga。虽然redux-thunk加上async await可以基本满足业务开发的需求。但是我感觉redux-saga更优雅一点。主要是它让我们发起一个异步action时,能像发起同步action一样,其次就是它的监视和执行的机制吸引了我,本着学习的目的,选用redux-saga处理异步action(当前它很适合用来测试)。UI框架为了迅速开发就选用了antd-mobile。发起http请求就用了axios。脚手架就用了create-react-app。
编码
这里主要说下编码时遇到的问题和解决的方法:
- 首先是路由的懒加载。react-router这个项目用了3.x的。然后,由于是web app而且是一个单页面应用。当项目变大时,打包后的js太臃肿。用户第一次进到这个页面,要下载太大的js导致首屏加载太慢。所以路由的分块是很必要的。但是,重点来了。react-router官方的文档,动态路由是webpack1的require.ensure,这个不是什么很大的事,主要那个写法也不太一样了。下面旧新对比:
折腾一个小时,总算搜到正确的写法,并达到了分块的效果。
- 其次antd-mobile的listview。这个组件用于展示列表。其中有一个属性是 useBodyScroll, 意思就是以body作为滚动的容器。这个项目有一个需求,就是在详情页时,评论就是一个长列表。那么我自然是想让它以body作为滚动容器,但是,一直触发不了到达底部的事件,除了一开始可以触发一次。百思不得其解,干脆,就自己监听body的滚动事件,判断到达底部,然后调用loadMore的事件,加载评论。
注意组件的更新顺序。父组件render时,会等子组件渲染完了,才会DidMount,所以如果子组件和父组件都为一个dom绑定了一个事件的话,最后父组件的绑定会覆盖子组件的。
然后还是路由。举个例子: /user/1 => /user/2,这类转跳,是不会触发组件的生命周期的,我在vue也遇到过。暂时没去看源码,首先我想到的解决方法就是当这类转跳发生时,比较两个路由,如果除了参数那部分都一样的话,就提取新路由的参数,更新数据,重新渲染。如果你有更好的方法,告诉我谢谢!
还有一个就是引入模块的。假设一个模块里有好几个函数或组件,但是我们只要用其中一个,我们这样导入时
import { x } from y;
webpack可是会帮你把这整个模块都打包进来的,如果这个模块有1000个函数或1000个组件,那么为了引入一个,打包其余的999个。。可想而知问题多大了。最后就是减少重复代码吧。比如我的收藏,最近回复,最近话题等的样式和逻辑都很类似。那么没必要都写一遍啊。封装一个组件,然后根据需要传props进入就可以达到复用的目的。长列表组件也是。没必要为每个长列表都写一遍。你只要抽取其中的逻辑,封装起来,通过传入props来个性配置使用就好。
大概就上面这么多。其余一些由于断断续续开发,没有及时记录下来,所以忘了。改天回忆一下。
测试
测试就暂时没做,手动测试了一遍。
反思
一个产品的开发流程,到我这就剩上面的几部分。开发这个web app时,对于 redux掌管数据,react只要负责视图渲染的说法有了一些新看法。对于庞大的项目来说,这样分开,应该很方便维护。react的组件尽量是无状态的组件的话,我们只要管好数据,它就会正常地工作,这也是纯函数的优点,关注点比较专一。也方便合作,比如一个前端工程师负责页面UI,一个负责数据。这样合作起来,找bug也很方便。但是开发小型应用时,这样有点大材小用,就把方便的事情硬是搞复杂了。所以,使用redux的话,不用用到react就下意识决定用redux吧。综合考虑,如果项目不小,而且未来会越做越大,解耦是最好的,数据和UI分开,后期方面增加新的东西,又不会显得臃肿,一团麻花。如果做些小项目练手或者未来不会计划开发下去的,直接在组件的state来保存数据也可以。
关于轮子。工程开发如果用成熟的轮子能完美解决是最好的。那就尽量别自己写轮子。毕竟人家的star就证明是千锤百炼的了。但是有时候,实在解决不了,可以选择看源码,找问题。也可以造轮子,达成业务需求。也建议我,你们平时多看源码, 理解实现原理对于开发也是很有帮助的。
关于写代码,写代码前先想好再写吧。真的,不然发现实现不对或者和需求不符合,你又得再来过。比如,路由分块,一开始觉得怎么简单怎么来,没意识到页面越来越多,分块的需求越来越重要,那么你又得重新写router哇。而且那一大堆路由,有得你写的了。如果平时加一个页面就写好了,那就不用付出这多一分劳累了。再比如,我开发点赞评论的saga时,脑子一热,觉得点赞和取消不就是一个流程么,点赞后,才能触发取消点赞的action。这里就没有考虑到,一个用户同时需要多好几个人点赞,但是这个时候并不需要取消点赞。那么按一开始的方法写,点赞后,只能接受到取消点赞的action,并执行完这个异步http, 才能再接受到点赞的action。那么用户除了第一个点赞的评论正确执行外,其余的都会被忽略到。那就发生了错误。所以写的时候就得仔细想好逻辑。