react+redux+webpack移动端项目总结

前言

距离我进新公司也有一个多月,这一个月的事件使用react写了一个项目,期间断断续续重构了两三次,目前已经完成第一阶段测试,也总结分享一些使用react的一些坑。

react

先啰嗦几句讲一下react原理,新人可以认真看下,老鸟可跳过。

react并没有像其他如vue,ng一样采用MVVM模式,所谓MVVM模式,狭义来说就是将模板与数据绑定在一起,当数据发生改变时,模板自动更新,这是中间的VM,最左边的M可以理解为我们看到的页面,而最右边的M可以理解为原始数据(例如数据库数据)。
其实要知道,这些框架模式归根结底的目的希望使代码更容易开发和维护。当你写一个小页面你不觉得什么,但是当你的页面越来越庞大,越来越复杂,开发人员走了一批又一批的时候,你就会明白了。而如何解决,现在比较公认的理念一个是组件化,将页面拆分成一个个组件,其实拆分成组件的目的并不全是为了复用,我觉得更多是为了维护;一个就是希望让应用层的编程能更专注于业务逻辑,那么这些框架都去做了处理,减少了大量DOM操作,让业务开发更加专注。

那么我们看看react采用的是什么原理。其实react采用的方法简单粗暴:它并没有对模板做数据绑定,而是每当数据变化时,就重新渲染模板。这有一个很大的好处就是每当数据变化时,对页面来说只有一次IO操作,而单纯的双向绑定更新DOM会有很多次;但有一个问题,如果只改变了一个dom的数据,整个模板都会重新渲染。那react解决的方法是每当数据改变时,就进行对比。

那么该如何对比呢,最简单的方法是每当数据改变,就去页面获取相应的DOM信息,然后与现在的DOM信息做比较。这个方法有个致命的缺点就是每次有DOM改变,就会有许多读取操作,IO操作太多,很影响性能。那么可以通过空间换时间的方法,将DOM信息保存起来,就避免了去页面获取信息的IO操作。那么我们看看一个真实DOM有多少数据

domproperty.png

虚拟DOM

如果我们把所有原生DOM缓存起来进行比较显然内存会爆炸,而我们所需要的仅仅是几个为数不多的状态信息(例如style啊这些),这时虚拟DOM应运而生,如果说原生DOM是一块猪肉,那么虚拟DOM就是这块猪肉中多精肉,他剔除了那些对我们来说没有太多意义相反还占内存的状态信息,而只将我们所需要的内容留了下来。那虚拟DOM该如何比较呢,就涉及到了虚拟DOM的diff算法。

diff算法

简单来说两个模板就像两棵树一样,传统的树对比的时间复杂度是O^3,也就是说要整棵树遍历三次,那react根据DOM的特点:跨层级的操作较少。什么叫跨层级,举个例子一个组件有三个层级关系(嵌套三层),把第二层的div放到第三层就属于跨层级操作。这种操作其实还是比较少的,react官方也不推荐这么写。那么利用这个特点,react只diff同层级的DOM。这里涉及以下几种情况

  1. tag变化(标签变化)
  2. 属性变化

第二种没什么好说,就是进行同层级对比。这里详细说一下第一种变化,react的方法是当前层级往下全部删除替换,简单暴力。在业务开发来看,你同层级类型都不同了,比如div变成了input,那么你的子组件相同的几率也较小,因此不如整个替换简单暴力。同时这也说明为什么列表需要key属性,因为列表很多的删除操作对于react来说是不知道的,它需要一个key来了解到底谁是谁。

踩过的一些坑

state

作为前端,拿到原型第一件事就是要与你的产品充分沟通,评估该项目是否需要引入redux,那么如何确定需要引入redux呢,这边有几点:

  1. 页面之间组件之间通信较多,且是跨层级的;
  2. 页面的交互逻辑较复杂,且经常引起多处组件变化。

再然后就是对state的设计。对于后台的返回的数据,你并不知道到底哪些是有用的,哪些可能现在没用以后有用,因此我的建议是对于每个api都将它存在一个object里。那么组件该如何去获取,首先不能全部通过顶部container获取依次往下传,也不能粒度很细的去一个个connect,我的建议是对于一个object,可以用一个container去connect,粒度把握主要看你的业务需求。

还有一个要不要全局都使用redux。我的观点是否定的,我认为对于局部一个组件内的状态完全可以通过setState来满足。

图片处理

首先将图片做一些划分。例如以500k作为分界,小于500k为小图片,否则是大图片。对于小图片,我们需要做如下判断:

  1. 页面是否重复使用?是就用雪碧图,否则转base64.
  2. 对于大图片,可以进行压缩后使用。

base64可以用webpack的url-loader替换。
举个例子

require('url?limit=250!./xxx.png')
//这里就会使用url-loader,假如图片小于250,就会转为base64

移动端适配

对于适配,我所知比较好的方法是利用rem作为单位,将页面宽度等分成10个rem,根据页面动态的用js去改变font-size,达到适配不同浏览器的目的。例如爱疯宽320px,那么font-size设置为32px。那么10rem就是等于整个屏幕的宽度。但是有一个特例就是高清屏,一般高清屏的物理像素是实际像素的2倍,那么当你想显示一个宽度为1的边框时,在普通屏幕是1px,在高清屏可以有0.5px(问题是很多浏览器不支持,为将0.5px认为是0)。虽然都使用1px在两者屏幕上实际上是一样的,但是高清屏里的1px在射鸡师眼里是无法达到他对于1的要求的。于是就有一些解决方案,比较简单是是使用transform:scale(0.5)。那么还有一种解决方案就是阿里的移动端解决方案,原理是将页面整体scale缩小,然后放大font-size,来保证rem为单位的布局不变,但是px为单位的会被缩小。

性能提升

首先先确定需求,确实有这个需求的时候再谈。

懒加载

webpack其实会帮我们做第三方依赖的懒加载处理,那么针对react,我们可以通过现成的库来实现懒加载react-lazyload,或者使用webpack现成的

require.ensure([],()=>{
require('public.js')
})

来实现。

shouldComponentUpdate

其实这个钩子可以极大的帮助我们去提升性能,由于它的存在,我们可以自己判断哪些是我们组件需要的state,哪些是不需要的,那么这就可以阻止react进行不必要diff。但是有一个问题就是对于对象我们很难去判断他们是否相等,那么可以通过immutableJs的fromJS和is方法来解决这个问题。其实immutableJs的好处远不止于此,目前我也尚在填坑中。

使用不可变数据,可以更好的达到函数式编程,不仅利于单元测试,也更有利于后期维护整个大的state。因为他的不可变特点,我们不会在不经意见不小心改变了state,而引起不必要的问题。

创建组件的痛点

为了使组件中的css作用域相互独立,一般采用Css Module,那么为了使组件看上去更像组件,并且易于后期维护,一般我们会这样结构化组件文件:

folder.png

那么对于每一个初始的jsx,我们大多会这样初始化

import s from './App.scss'
import{Component} from 'react';//得到组件方法

class App extends Component{
  
  render(){
    return (
      <div className={s.container}>
      </div>
    )
  } 
}
export default App;


不难发现,对于每一个组件,我都需要去手动的创建这些文件和文件夹,而这些操作其实是重复且无意义的劳动,于是我造了一个小轮子,一个命令行小工具,来解决这个痛点。
react-component-maker,欢迎猛戳点star!

结语

困了,本宝宝要睡觉了,还有的内容下次再说吧,再见。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容