[sweep-it] 分享我学习和使用React的历程

前言:几天前我发了两个沸点,是关于我学习和使用React,并建立的一个minesweeper游戏。发现你们挺喜欢的,所以,我写了这一篇文章,以此来记录本身的历程,也但愿对你们有一点点帮助。html

static image

开始使用React并构建一个小项目

学习一门新的技术,最好的开始就是阅读官方文档,而后才开始本身的实践。所以,个人学习步骤能够概括以下:前端

  1. 带着一些思考去阅读React官方文档
  2. 理解React和周围生态,分析create-react-app工程结构
  3. 开始构思一个小小的项目,可以让本身在实践中学习。写项目过程当中遇到的问题,有几个解决途径
    • 社区生态:解决状态管理、路由等问题,甚至好的插件(在深刻了解以前,建议先用React自己去构建基础UI)。
    • 官方文档:基础概念加深印象。
    • StackOverflow:疑惑解析。
    • google一下(英文),每每有新发现。
  4. 参与社区,了解反馈。作游戏运营或者策划的同窗应该很清楚,若是作一件事按游戏的心态去作,成就感会挺高的,而且在这个过程当中不断获得反馈,这种反馈又激励你更大的求胜欲望。所以我在项目作得差很少的时候在掘金上发了一个沸点,发现你们挺喜欢这个项目,这也激励我继续写下去。
  5. 源码阅读。这个是终极状态,像Redux这种,代码量少,写得又很棒的库,读一读,收获挺大。好比有心人就会看到我仓库里面有个/test/compose.js,这个文件就是测试一下写写compose函数,想法来源也是Redux

首页开始分析

特色

  • 声明式:设计好UI,它就会按你设计得方式运行,react帮助您有效更新、正确渲染。
  • 组件化:一个组件封装好UI和逻辑(基于JavaScript而非模板),能够轻松地将组件进行组合,以构成更加复杂的页面。
  • 一次学习 随处编写React社区活跃,内容丰富,一种技术知足你服务端渲染和Native应用的需求。

从官方特色介绍,至少能够知道一些要点java

  • JavaScript:以js为技术基础来构建UI,若是js基础比较扎实,应该能够较快入门。
  • 组件化:组件化是目前前端开发的主流,浏览器甚至还在推广Web Component技术,这就要求咱们思考问题的时候,要常常想想,一个事物是否足够独立?是否足够小?是否可以知足大多数场景的须要?
  • 生态丰富:学习一门技术,能够快速知足多种应用场景。
  • 状态与DOM分离:前端界长提MVVM的概念,所谓ModelViewModel-ViewReact作到了数据(状态)和视图(DOM)分离。

所以,在学习React以前,我花了一些时间来复习JavaScriptDOM的一些基础知识,后来的学习中证实这种角度是对的。react

概览

  • 简单组件:render函数会在页面更新时,被React调用,用于生成一帧。是的我把它想象成一帧页面(以时间长度来看,一次render是页面生命周期的一帧)。至于为何是一个render函数,由于咱们的React是一个functionorclass,使用一个函数来更新页面会很方便区分和保留不一样的状态。(Vue里面data声明为一个函数,原理也是同样的。)
  • 有状态组件:使用props来获取从父组件传递来的状态,完成父子组件通讯。须要注意的是,React上的DOM不是原生的DOM,而是由React封装后的,包括事件(官方文档有讲解)。
  • 应用:在class组件的constructor中声明this.state,能够定义当前组件的内部状态,而且可使用this.setState()方法来更新这个状态,每次state被更新时,上面提到的render会被调用用于生成一个新的
  • 在组件中使用外部插件:因为React基于js来构建,那些第三方插件,很容易被引用进来。

技术文档

因为技术文档内容挺多的,我只挑选一些我以为重要的概念,并加以个人理解进行阐述。webpack

核心概念

  • jsx:组件中的松散耦合。在一个文件中采用jsx的语法书写DOMjs,这里须要了解语法,并在使用的过程当中实践。
  • props:让你能够从父组件传递消息到子组件内(包括事件/方法),消息通讯让状态传递成为可能,并且使用的语法和写html属性差很少,挺友好的。
  • state:组件内部状态(Model)。经过调用setState来更新state,并触发render来获得新的视图(View)。
  • 事件处理:注意class组件须要bind事件的this。这就是我在本文开始提到的bonus,在js基础中,搞清楚this的指向挺重要的。另外一个要点就是在React世界中,在DOM中直接触发的事件每每须要手动调用e.preventDefault()来阻止事件冒泡。
  • key:能够想象,在一组元素的对比和更新中,带有key会下降对比的工做量,加快咱们更新的速度。React内部维护了一个Virtual DOM的概念,让列表更新更快。
  • 状态提高:在子组件中发送数据到父组件。学到这里,基本的父子组件通讯就搞完了,原理就是调用props中获得的事件。
  • 哲学:切割页面,划分最小的组件对象,明确数据流向,明确事件分发方式。

高级指引

  • 语义化:这个每每被开发者忽视,实际上,读这个能了解别人解决问题的思考,适合看一看。
  • 代码分割:这个须要结合ES 6 Modulewebpack来看看,工程化的内容,待深刻。
  • Refs:因为React是本身包的DOM元素,所以在父类要想拿到子类中的引用(一般这种状况咱们须要从父类直接去调用子类的方法),就须要一个ref。被forwardRef以后实际是返回了一个高阶组件,在这里你可以拿到ref(被你从React.createRef()中建立的)。
  • 高阶组件:由于咱们使用的React全是对象,那么想提高对象的能力,很容易想到的就是给对象包一层外壳,在java里面常常要分什么do\dto\bo\ao\vo等等,在React,利用js的优点(函数乃第一公民),能够很天然获得高阶组件这种概念。原理就是:一个纯函数,处理一个组件,返回另外一个组件。
  • 性能优化:待深刻
  • 其余:待深刻

高级指引里面的内容,须要咱们在实践中反复地回看,所以,这里就不赘述,每一个人对这些有本身的理解吧。git

开始一个项目

每一个人都有本身的starter项目,我选择了minesweeper。这个游戏出现得挺早,可是我到高中上电脑课才从同窗那知道它的玩儿法。个人想法是:规则挺简单,不须要我写不少游戏逻辑,不须要路由,能够拆分好几个组件,须要一点点状态管理和组件通讯,正符合我这种初学React的人。程序员

前期准备

前期我阅读了几篇文章,主要是这一篇,做者用react写了一个minesweepergithub

react-minesweeper
经过阅读别人的文章和代码,基本了解了一个 做为项目而存在的React是什么个样子,接下来就只须要去实践它就好了。

接着我作了一些技术选型:web

  1. React固然是必选了。而且我选择使用你们都普遍使用的create-react-app做为cliredux

  2. Redux&React-redux:若是是一个小游戏,本不须要状态管理。我认为项目的统一状态管理应该出如今状态多且复杂,并且须要众多组件同时响应时。可是从小了说,任意组件的状态可能都是有意义的(受到多个其余组件引用、可能成为全局状态)。所以仍是选择使用react-redux,这样在我须要组件间通讯的时候,我能够少写不少跳转,只须要专一于写一个组件。

    简单介绍一下,我是如何理解和使用react-redux的。

    1. 理解reducer。这个单词直译为减小,在Array.prototype.reduce中,它减小了空间量,将先后空间量做用于一个reducer函数,使得array(多个数据)变成一个单一的数据。可是在redux概念里,reducer须要放到生命周期里来看,一个应用的生命周期中,reducer会被调用无数次,所以我理解为它是把时间上的多个变量减小为单一变量,可是由于时间没有中止(时间中止,则应用也中止了,变量也不存在),所以每次咱们只能拿到最终量的某一个时刻的样子,这就是reducer的产出被叫作nextState的缘由。
    2. 惟一数据中心store。这个很好理解,一个项目只须要一个大脑就好了,保持数据源一致。
    3. 映射(map)。无论是mapStateToProps仍是mapDispatchToProps,目的都是一个,把数据从store中取出来,挂载到UI组件上,以造成容器组件
    4. 容器(Container)。容器是一个高阶组件,它把本身获取到的StateDispatch转换为props挂载到UI组件上。使用时容器组件和被它包裹的UI组件是一个用法,区别是若是使用容器组件,咱们能够从this.props中获取到store内的state,也可以分发dispatch
    5. conbineReducer。能够了解一下compose的概念和使用场景。
  3. rxjs:最开始是想使用rxjs的,可是在写得过程当中发现不少事件都不必用,简单地使用事件就能够解决了,在这个项目中,rxjs带来的提高并不明显,所以放弃了。

  4. TypeScript:有网友问我为何没有用用TypeScript。由于,这个项目实在过小了,而我又须要快速完成它,若是我已经熟悉的语法和概念可让我快速开发一个应用,那么为了一些ts带来的小优点而放弃了我另外一个优点,那就得不偿失了。所以没有采用这个。

  5. redux-thunk:当我写到游戏状态更新、动画这一块的时候,我确实须要一些异步dispatch的能力了,这时候我选择引入redux-thunk。固然,知道这个库,也是google,从社区中了解到的。

完成技术选型,剩下的就是写起来。

写一个小项目

无论是小项目仍是大项目,写的初衷有两个:

  1. 学习基本的React,为以后的工做作一些准备
  2. 反馈社区。本身从社区学习了不少优秀的思想,所以若是可以写一点点东西,帮助到和我同样的初学者,那再好不过了。
工程结构

我喜欢将一个项目各部分的职责划分得清楚一些

  • test:放置测试代码。单元测试,测试一些优秀的代码等等。
  • assets:放置静态资源。大可能是图片。
  • components:放置组件。组件须要划分各自的职责,按模块/语义化名字来取。
  • constant:放置常量。字符串、数字等等。有点像java里面的enum
  • utilorhelper:辅助函数。和个人ui无关、state无关的内容,放置到这里。有些要是和业务强相关的话,可能会增长一个business目录。
拆分组件

要说minesweeper,首先想到的是一个面板,加一点游戏辅助信息。所以,我根据一个物件在页面出现的位置,划分了各个组件的职责。

  • Board:游戏面板。用于放置地图、辅助信息等。
    • 可能设计为横向布局:辅助信息|地图|描述信息
    • 也可能设计为纵向布局
    • 甚至你可让辅助信息都在另外一个页面,让游戏地图单独一个页面
  • Cell:方块。一个方块有多种状态,所以能够这么思考:
    • 翻开
      • 地雷
      • 数字
      • 空白
      • 多重图案
    • 未翻开
      • 空白
      • 加点色彩
  • Clock:时钟,这个可能会被全局用到,所以抽象为一个组件。
    • 表现形式能够多种多样
    • 对外提供时间状态到store
  • Description:用来写一些游戏描述信息
    • 游戏简介
    • 如何操做
  • Emoji:做为一个基于程序员和用户都喜欢的图标--emoji--来建立的项目,抽象出一个Emoji组件是很天然的事。(一个项目多个部分都会用到)
  • Info:展现游戏辅助信息,扩展性比较强
    • 能够设计分数
    • 展现游戏难度,甚至能够定制游戏方块
    • 游戏状态显示
    • 标记个数
    • 地雷总数
    • 时间显示
    • 若是加入对战,能够显示别人当前分数
    • 是否能够加入背景图像切换(背景不同,难度不同?)
    • 是否能够加入音乐(音乐紧凑程度能够反映了游戏难度)
  • Matrix:方块地图,整个游戏的互动区域
    • 若是是PC 这个Matrix就是游戏渲染屏幕,游戏地图
    • 但我也能够用来播放一些自定义的动画
    • 动画自己就是游戏的一部分
  • Row:为了更好地渲染Cell,在MatrixCell之间增长一层Row
重要部分
  1. 使用class语法:任什么时候候都要明确你的this指向在哪里。
  2. react-redux的灵活使用:在须要状态和不须要状态的情形下要作取舍;纯函数更新;异步更新;有什么好处。
  3. dispatch:分发鼠标事件到全局,用于更新store,并让各个部分有机刷新。
  4. 生命周期:这个在个人项目中用的少,可是单独提出来明确一下,你们使用一个技术时,必定要知道它各个部分会作些什么事。
  5. 拆分和组合:这个你们应该懂,整个程序员生涯都脱离不了这两个概念。
  6. 良好的分割
  7. 良好的UI

最后这两点(6/7)为啥很重要,我是这么思考的:

  1. 良好的业务和代码分割可以让新接手项目的更快上手(若是别人但愿基于你的项目作定制,会有一个良好的体验)
  2. 多花一点时间去设计UI,可让更多人喜欢上你的产品,由于你们都是从第一印象开始认识你的。

到这里,基本上我贡献了从开始阅读React文档到输出一个minesweeper游戏的全部思考。

  • 但愿可以帮助到你们。
  • 但愿能获得更多反馈,可以一块儿交流。

最后奉上项目地址,谢谢你们。

(以上文章仅来自做者(我)我的观点)

相关文章
相关标签/搜索