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

前言

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

react

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

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

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

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

domproperty.png

虚拟DOM

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

diff算法

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

  1. tag变化(标签变化)web

  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!

结语

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

相关文章
相关标签/搜索