React学习心得浅谈

React学习浅谈(1)-技术栈

这两天花了点时间学习了下React,本人并不是一名纯前端研发人员,之所以想学习React只是想补全自己的技术栈。之前一直都是使用jquery+bootstrap来开发页面,其实大多数情况下这种技术栈也够了。但是现在都流行前后端分离,所以诸如React和Vue这类MVVM前端框架才会大行其道。

这所以写这篇文章,主要还是为了对自己这两天的学习做个总结,免得后面遗忘。同时,也希望能给那些想学习React却比较迷茫的同行们来个抛砖引玉,说下我个人的学习路线。

我觉得React的优点在于组件化以及JSX语法。组件化实现了页面通用元素的封装,提高页面元素的复用性;而JSX语法则便于我们在js中编写html代码。

1. React技术栈

学习React是有一定的学习成本的,主要是如果想要用它进行项目开发,就需要学习一系列它的技术栈,包括基本知识、运行编译环境和一系列插件。而我也只是学了个冰山一角。

1.1. 运行编译环境

我采用的nodejs+npm+yarn+webpack。

  • Nodes:javascript运行环境,我们编写的代码需要在nodejs上运行。

  • npm:在安装完nodejs后,默认就已经按转了npm了。npm是包管理软件,能够快速地基于命令行的方式安装各种组建包,并对组建包进行管理。例如:

    npm install -g create-react-app --save-dev
    
  • Yarn:yarn和npm功能类似,都是对包进行管理。yarn具有缓存包的功能,下载过一次,下次安装可以直接从本地进行安装。

    yarn add react-redux
    
  • Webpack:打包工具,用于将javascript进行打包。

1.2. ES6

要学习并使用react,ES6是必须要学习的。在react开发过程中,会大量地使用到ES6中的各种特性。诸如:

  • class类:例如class InputComponent extends React.Component
  • let/const:定义变量、函数会大量使用到let和const,而不会再去使用var;
  • import/export:需要使用import引入组件,并将自己写的组件通过export输出,方便其他组件引用;
  • 模板字符串:便于编写字符串,不需要通过+来组装字符串。
  • Object.assign():用于将两个对象进行合并。

还有其他很多特性会用到,所以对ES6的学习非常重要。

1.3. React

React是基于组件化的思想进行开发的js框架,所以我们需要有组件化的思想。学习React主要会用到:

  • jsx语法:通过该语法方便在js中编写html代码;只能有一个顶级元素!
  • React.Component:这是React组件的基类,所以编写的React组件都要继承这个类。组件之间的参数的传递采用this.props进行传递。
  • ReactDOM:用于将组件渲染到页面上。

1.4 Redux

Redux用于对JavaScript的状态进行管理,通过Redux,可以有效衔接页面操作和操作完成后的状态之间的关系,以及基于双向绑定实现状态对监听状态变化的监听器的影响。所有的状态数据存储在同一个Store中。

其中一个词:状态,很重要。我们在使用Redux,在动作产生后(例如页面的一个点击事件),那么传递给状态的不是对事件的处理动作,而是事件完成后的状态。例如点击登陆按钮进行登录,状态不是执行动作的事件,而是动作完成后的状态:用户名密码是什么?验证是否通过?

所以Redux会涉及到四个概念:

  • Action:该动作不是点击事件的动作,而是点击之前或者点击之后设置状态的动作。例如:

    const loginReceived = (checked)=>{
        type:'login_received',
        checked
    }
    

    从上面可以看出,我们传递的不是事件,而是是否验证通过这个状态。

  • Reduce:用于接受action产生的状态,并对store中的状态进行修改。所以reduce会在创建store时作为参数传进去,一旦有action被dispatch到store中,store就会调用reduce进行处理。Reduce是一个纯函数。并且只能有一个。多个Reduce通过combineReducers进行组合。

  • Dispatch:动作分发,将动作分发到store中。

  • Store:用于存储状态State。

1.5 Middleware

那么既然用于传递的是用户名、密码、是否通过,那么“验证”事件什么时候执行呢?理论上应该是在状态——获取到是否通过——之前:动作—>验证—>状态。

也就是说“验证”这一步是发生在Action发生之后,Reduce之前。这里就涉及到middleware组件。middleware是一个概念,类似于拦截器,用于拦截每一个dispatch到store中的action,在action发生之前和发生之后进行拦截处理。

例如记录日志,可以使用createLogs,上面说的中间处理,可以使用redux-thunk

2. 环境搭建

环境搭建包括开发环境和编译环境。

2.1 搭建开发环境

我主要是用VS Code进行开发,优点不多说,绝对好用就是了。需要安装一些插件才能发挥更强大的作用。我装的插件如下图所示:

在这里插入图片描述

2.2 搭建编译环境

  • 安装nodejs。这个可以直接下载安装包进行安装,安装完成后,也就支持npm了。

  • 安装yarn。windows平台下下载安装包安装,mac可以使用homebrew进行安装。

    brew install yarn
    
  • 切换淘宝镜像:

    npm config set registry https://registry.npm.taobao.org
    
  • 安装cnpm

    npm install -g cnpm 
    
  • 安装react开发环境创建组件。

    npm install -g create-react-app
    

    以后可以直接使用create-react-app projectname 来创建开发环境,会默认初始化好开发环境需要的基本依赖。

2.3 搭建完整的项目开发环境

接下来介绍如何搭建一个完整的项目开发环境。例如项目名称是一个天气查询项目,展示当前的天气。那么我们可以在命令行下做如下操作:

cd Documents/projects/
create-react-app weather

等待项目初始化环境创建完成后,可以通过yarn安装其他以来包:

yarn add redux
yarn add react-redux
yarn add redux-logger
yarn add redux-thunk
yarn add cross-fetch

如果需要其他依赖包,也可以这样安装即可。

3. 编码设计

我们就以编写一个获取天气的简单小项目来上手。

3.1 创建项目目录

默认我们在src目录下创建四个子目录:

  • actions:用于存放action的js文件。再次记住:action不是事件函数,是传递状态state的修改值的函数。
  • reduces:用于存放reduce的js文件。
  • containers:用于存放将state、dispatch方法与有状态组件(也就是用于最后渲染界面的组件)进行连接的函数。
  • components:用于存放无状态组件和有状态组件的函数。
    • 无状态组件:纯组件,不关心state,只根据传递的props编写html元素的组件。例如一个input或者button组件,而组件中的动作也会通过参数触发有状态组件中的函数,从而实现对状态的修改。
    • 有状态组件:需要关心和设置state,可能会包含多个无状态组件。最终会通过 ReactDOM.render 渲染成页面的组件。

可能我们还会创建utils目录或者其他目录。最后,还有一个最外层的index.js文件,我们一般在这里创建store,并渲染页面。

3.2 编写action

编写action,我们需要分析页面获取天气会产生几个事件。页面的功能是:“根据选择的不同地市,获取该地市的天气,将获取到的地市展示在界面上“。根据这句话,我们来分析有哪些action。

  • 选择不同的地市:”选择“是事件,也就是onChange或者onClick事件。选择的“地市”就是状态值。所以我们会建一个selectedCity(cityCode)的函数。注意方法名是selected,而不是select,用的是过去式,表示被选择的,是一种状态——天气“待获取”。
  • 获取该地市的天气:从字面上看,应该是发起ajax请求获取天气。但是默认的action是不能发送ajax请求的,只传递状态。这里传递什么状态?那就是天气“获取中”,所以我们会建一个requestWeather(cityCode)的函数。那ajax在哪儿发起呢?会用到前面说的redux-thunk来发起。
  • 将获取到的天气展示在界面上:自然而然,我们会看到,这里的状态是“已获取”到天气,那么我们传递的窗台值就是获取到的天气信息,可以是json。所以我们会创建一个receivedWeather(cityCode,json)的函数。
  • 最后就是ajax请求函数。该函数通过redux-thunk来编写,同时会调用requestWeather(cityCode)receivedWeather(cityCode,json)函数,来完成获取天气之前的准备动作(例如弹出转圈等待)和获取到天气之后的动作(例如渲染到页面)。所以我们会创建一个fetchWeather(cityCode)函数。

3.3 编写reduces

因为reduce是用于修改state的,并且是一个纯函数。那么首先第一步,也是最重要的就是想想看我们的state长什么样子?也就是什么样的数据结构(json结构)。

{
    selectedCity:'xxx', //选择的地市
    weatherInfo:{//天气信息,是一个json
        
    },
    isFetching:true/false //是否获取中,如果是ajax请求中,则是true,否则是false。
}

想好了state长什么样子,就要考虑编写几个reduce函数呢?我这里有个个人看法,就是看state里有几个顶级的key,就写几个函数。例如上面有selectedCityweatherInfoisFetching三个顶级key,那么我们就创建三个同名的函数。为什么要这样呢?一是为了方法的独立性,便于方法重用;二是正好基于combineReduces函数,在集成这三个reduce函数后,就会生成如上的数据结构。

既然是写三个函数,同时也说了这样可以保证方法的独立性。那么每个函数返回的state也需要相应的只返回对应的独立的结果。例如selectedCity函数返回的state就只是一个字符串。是不是很独立呢?

3.4 编写components

编写components,就需要考虑:

  • 页面长什么样子,哪些页面元素是无状态组件,哪些是有状态组件;
    • select 组件是无状态组件
    • weatherApp 是有状态组件,里面包含select组件。
  • 在编写组件的时候,需要考虑state里有什么元素,哪些元素是组件需要用到的;
    • select 组件会用到 selectedCity 的值;
    • weatherApp 会用到 weatherInfo 的值;同时还会根据 isFetching 的值显示“加载中…“。
  • 还要考虑组件触发的事件( `onClick``)会调用哪个action。
    • select 组件的onChange事件会触发 selectedCity 函数;
    • weatherAppcomponentWillReceiveProps() 方法会触发 fetchWeather 函数,用于监听一旦selectedCity 的值发生变化,就获取天气。

3.5 编写containers

containers的写法一般是固定的,就三个作用:

  • 将state的值传递给组件的props,我们会创建mapStateToProps(state)方法;(当然也可以不写这个函数,那就是将state作为props的一部分传递给组件)
  • 将dispatch各个action的函数传递给组件的props,方便业务调用(当然也可以直接传dispatch作为props的一部分),我们会创建 mapDispatchToProps(dispatch)方法;
  • 调用 connect 方法,将组件与redux连接起来,并将上面的两个方法作为connect的参数。

经过上面的分析,我们就可以编写代码了,分别在对应的目录下创建js文件,并在js文件中创建对应的方法。

猜你喜欢

转载自blog.csdn.net/twypx/article/details/85238613