React相关

React 是一个采用声明式,高效而且灵活的用来构建用户界面的框架。

JSX

本质上来讲,JSX 只是为React.createElement(component, props, ...children)方法提供的语法糖。比如下面的代码:

const element = (
<h1 className="greeting">
Hello, world!
</h1>
);

编译为:

const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);

React.createElement()这个方法首先会进行一些避免bug的检查,之后会返回一个类似下面例子的对象:

const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world'
}
};

这样的对象被称为React元素,它代表所有你在屏幕上看到的东西。
我们用 React 开发应用时一般只会定义一个根节点。要将 React 元素渲染到根DOM节点中,我们通过把它们都传递给ReactDOM.render()的方法来将其渲染到页面上:

ReactDOM.render(
element,
document.getElementById('root')
);

每当 React 元素发生变化时,ReactDOM首先会比较元素内容先后的不同,然后操作浏览器DOM更新改变了的部分。

组件 & Props

当 React 遇到的元素是用户自定义的组件,它会将 JSX 属性作为单个对象传递给该组件,这个对象称之为props。无论是使用函数或是类来声明一个组件,它决不能修改它自己的 props 。
例如,这段代码会在页面上渲染出Hello,Sara:

//使用 ES6 class 来定义一个组件,组件名称必须以大写字母开头。
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
} const element = <Welcome name="Sara" />;
ReactDOM.render(
element,
document.getElementById('root')
);

我们来回顾一下在这个例子中发生了什么:

  1. 我们对<Welcome name="Sara" />元素调用了ReactDOM.render()方法。
  2. React 将{name: 'Sara'}作为props传入并调用 Welcome 组件。
  3. Welcome 组件将<h1>Hello, Sara</h1>元素作为结果返回。
  4. ReactDOM 将DOM更新为<h1>Hello, Sara</h1>。

State & 生命周期

组件的通过props获取属性,且其不能修改;当我们需要修改当前组件的状态时,要用到state来设置局部状态,需要通过this.setState()来更新组件局部状态:

class Toggle extends React.Component {
constructor(props) {
super(props); //初始化this,并赋值this.props
this.state = {isToggleOn: true}; //初始化this.state
this.handleClick = this.handleClick.bind(this); //为this.handleClick绑定this对象
} handleClick() {
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
})); //用this.setState()更新this.state
} render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
} ReactDOM.render(
<Toggle />,
document.getElementById('root')
);

每一个组件都有几个你可以重写以让代码在处理环节的特定时期运行的“生命周期方法”。方法中带有前缀will的在特定环节之前被调用,而带有前缀did的方法则会在特定环节之后被调用。

  • 装配:这些方法会在组件实例被创建和插入DOM中时被调用:

    - constructor(`props`)
    - componentWillMount()
    - render()
    - componentDidMount()
  • 更新:属性或状态的改变会触发一次更新。当一个组件在被重渲时,这些方法将会被调用:

    - componentWillReceiveProps(`nextProps`)
    - shouldComponentUpdate(`nextProps`, `nextState`)
    - componentWillUpdate(`nextProps`, `nextState`)
    - render()
    - componentDidUpdate(`prevProps`, `prevState`)
  • 卸载:当一个组件被从DOM中移除时,该方法被调用:

    - componentWillUnmount()

当项目视图交互复杂且频繁的时候,依旧采用 state 进行状态更改会显得异常繁琐和不可预测。
这时我们就需要借助 Redux 框架,将状态数据全部转交给 Redux 处理,React 专一负责视图显示,这样会让项目逻辑变得简单而清晰。

Redux相关

三大原则:

  • 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个store中。
  • 惟一改变 state 的方法就是触发action,action 是一个用于描述事件的普通对象。
  • 为了描述 action 如何改变 state tree ,你需要编写reducers。

Action

Action 是把数据从项目传到 store 的有效载荷。它是 store 数据的唯一来源。通常你会通过store.dispatch()将 action 传到 store。

Action 本质上是 JavaScript 普通对象,添加新 todo 任务的 action 是这样的:

{
type: 'ADD_TODO',
text: 'Build my first Redux app'
}

Action 创建函数就是生成 action 的方法。在 Redux 中的 action 创建函数只是简单的返回一个 action:

function addTodo(text) {
return {
type: 'ADD_TODO',
text: text
}
}

这样做将使 action 创建函数更容易被移植和测试。只需把 action 创建函数的结果传给 dispatch() 方法即可发起一次 dispatch 过程。

dispatch(addTodo(text));

//或者创建一个 被绑定的 action 创建函数 来自动 dispatch:
const boundAddTodo = (text) => dispatch(addTodo(text));
boundAddTodo(text);

store 里能直接通过 store.dispatch() 调用 dispatch() 方法,但是多数情况下你会使用 react-redux 提供的connect()帮助器来调用。

Reducer

Action 只是描述了有事情发生了这一事实,而reducer要做的事情正是指明应用如何更新 state 。reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。

(previousState, action) => newState

保持 reducer 纯净非常重要。永远不要在 reducer 里做这些操作:

  • 修改传入参数;
  • 执行有副作用的操作,如 API 请求和路由跳转;
  • 调用非纯函数,如 Date.now() 或 Math.random()。

我们将以指定 state 的初始状态作为开始。Redux 首次执行时,state 为 undefined,此时我们可借机设置并返回应用的初始 state:

const initialState = {};    //初始化state

function todoApp(state = initialState, action) {
switch (action.type) {
case 'ADD_TODO':
return Object.assign({}, state, {
text: action.text
})
default:
return state //在 default 情况下返回旧的 state
}
}

每个 reducer 只负责管理全局 state 中它负责的一部分。每个 reducer 的 state 参数都不同,分别对应它管理的那部分 state 数据。

combineReducers()所做的只是生成一个函数,这个函数来调用你的一系列 reducer,每个 reducer 根据它们的 key 来筛选出 state 中的一部分数据并处理,然后这个生成的函数再将所有 reducer 的结果合并成一个大的对象。

import { combineReducers } from 'redux';

const todoApp = combineReducers({
visibilityFilter,
todos
}) export default todoApp;

注意上面的写法和下面完全等价:

export default function todoApp(state = {}, action) {
return {
visibilityFilter: visibilityFilter(state.visibilityFilter, action),
todos: todos(state.todos, action)
}
}

combineReducers 接收一个对象,可以把所有顶级的 reducer 放到一个独立的文件中,通过 export 暴露出每个 reducer 函数,然后使用 import * as reducers 得到一个以它们名字作为 key 的 object:

import { combineReducers } from 'redux'
import * as reducers from './reducers' const todoApp = combineReducers(reducers)

Store

action 描述发生了什么,reducers 根据 action 更新 state,Store就是把它们联系到一起的对象。Store 有以下职责:

  • 维持应用的 state;
  • 提供getState()方法获取 state;
  • 提供dispatch(action)方法更新state;
  • 通过subscribe(listener)注册监听器;
  • 通过subscribe(listener)返回的函数注销监听器。

我们使用 combineReducers() 将多个 reducer 合并成为一个。现在我们将其导入,并传递 createStore()。

import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)

createStore() 的第二个参数是可选的, 用于设置 state 初始状态。这对开发同构应用时非常有用,服务器端 redux 应用的 state 结构可以与客户端保持一致, 那么客户端可以将从网络接收到的服务端 state 直接用于本地数据初始化。

let store = createStore(todoApp, window.STATE_FROM_SERVER);

数据流

Redux 应用中数据的生命周期遵循下面 4 个步骤:

  1. 调用 store.dispatch(action)。
  2. Redux store 调用传入的 reducer 函数。
  3. 根 reducer 应该把多个子 reducer 输出合并成一个单一的 state 树。
  4. Redux store 保存了根 reducer 返回的完整 state 树。

Router相关

直接使用整合后的react-router-redux,后面抽时间再详细讲一下,具体使用的话模仿官方案例吧,官方文档。

容器组件 和 展示组件

Redux 的 React 绑定库包含了 容器组件和展示组件相分离 的开发思想。

明智的做法是只在最顶层组件(如路由操作)里使用 Redux。其余内部组件仅仅是展示性的,所有数据都通过 props 传入。

系列目录

  1. 前端大统一时代即将来临?
  2. React项目实战:环境搭建
  3. React项目实战:react-redux-router基本原理
  4. React项目实战:登录页面(编辑中)

React项目实战:react-redux-router基本原理的更多相关文章

  1. 如何在非 React 项目中使用 Redux

    本文作者:胡子大哈 原文链接:https://scriptoj.com/topic/178/如何在非-react-项目中使用-redux 转载请注明出处,保留原文链接和作者信息. 目录 1.前言 2. ...

  2. 如何优雅地在React项目中使用Redux

    前言 或许你当前的项目还没有到应用Redux的程度,但提前了解一下也没有坏处,本文不会安利大家使用Redux 概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与 ...

  3. 优雅的在React项目中使用Redux

    概念 首先我们会用到哪些框架和工具呢? React UI框架 Redux 状态管理工具,与React没有任何关系,其他UI框架也可以使用Redux react-redux React插件,作用:方便在 ...

  4. 七天接手react项目 系列 —— react 脚手架创建项目

    其他章节请看: 七天接手react项目 系列 react 脚手架创建项目 前面我们一直通过 script 的方式学习 react 基础知识,而真实项目通常是基于脚手架进行开发. 本篇首先通过 reac ...

  5. 七天接手react项目 系列 —— react 路由

    其他章节请看: 七天接手react项目 系列 react 路由 本篇首先讲解路由原理,接着以一个基础路由示例为起点讲述路由最基础的知识,然后讲解嵌套路由.路由传参,最后讲解路由组件和一般组件的区别,以 ...

  6. react全家桶从0搭建一个完整的react项目(react-router4、redux、redux-saga)

    react全家桶从0到1(最新) 本文从零开始,逐步讲解如何用react全家桶搭建一个完整的react项目.文中针对react.webpack.babel.react-route.redux.redu ...

  7. 《Node+MongoDB+React 项目实战开发》已出版

    前言 从深圳回长沙已经快4个月了,除了把车开熟练了外,并没有什么值得一提的,长沙这边要么就是连续下一个月雨,要么就是连续一个月高温暴晒,上班更是没啥子意思,长沙这边的公司和深圳落差挺大的,薪资也是断崖 ...

  8. 在react项目当中使用redux

    如果需要在你的react项目当中使用状态管理模式的话,需要引入redux和react-redux两个插件,redux提供基本的功能,react-redux提供将redux注入react的方法. imp ...

  9. asp.net core react 项目实战(一)

    asp.net-core-react asp.net core react 简介 开发依赖环境 .NET Core SDK (reflecting any global.json): Version: ...

随机推荐

  1. Spring Boot中@Async的作用

    在Spring中,@Async这个注解用于标记的异步的方法.方法上一旦标记了这个方法,当其它线程调用这个方法时,就会开启一个新的线程去异步处理业务逻辑. 此注解的使用说明: 1.此注解可以用在方法上, ...

  2. 把Java代码转成c#可用的dll

    1.首先你需要到 IKVM官网 下载IKVM.http://sourceforge.net/projects/ikvm/files/,需要注意的是如果你用的是.net framework2.0,那么最 ...

  3. single-value grouping |limit grouping|cutpoint grouping|Lower class limit|Upper class limit|Class width|Class mark|rounding error or roundoff error|Histograms|Dotplots|Stem-and-Leaf

    2.3 Organizing Quantitative Data group quantitative data: To organize quantitative data, we first gr ...

  4. django操作非ORM创建的表

    问题:django的ORM怎么连接已存在的表,然后进行增删查改操作?     工作中会遇见很多二次开发的时候,表都是已经创建好的,用django的ORM进行二次开发,怎么操作数据库中的表呢? 下面介绍 ...

  5. python3多线程应用详解(第二卷:多线程到底是怎么工作的)

    现在很多人都说用多线程工作快是因为多个不同任务可以同时执行,注意我说的是不同任务,要是重复做一件事达到相同效果就是画蛇添足了,其实这是个错误的说法,线程真正的本质是无法同时执行的.现在我们来看下多线程 ...

  6. JarvisOJ level3_x64

    这一题是和前面x86的差不多,都是利用了同一个知识点,唯一的区别就是使用的堆栈地址不同,x86是直接使用堆栈来传递参数的,而x64不同 x64的函数调用时整数和指针参数按照从左到右的顺序依次保存在寄存 ...

  7. 数据结构中的顺序表和链表(Python语言)

    转载:https://blog.csdn.net/weixin_43187669/article/details/96426362 算法是为了解决实际问题而设计的,数据结构是算法需要处理的问题载体. ...

  8. Nginx笔记总结十二:nginx版本号隐藏

    vim nginx.conf http { server_tokens off;} php-fpm fastcgi.conf或fcgi.conf fastcgi_param SERVER_SOFTWA ...

  9. 关于Synchornized,Lock,AtomicBoolean和volatile的区别介绍

    1.  volatile 变量可以被看作是一种 "程度较轻的 synchronized". 2.  Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的 ...

  10. ssm框架下怎么批量删除数据?

    ssm框架下批量删除怎么删除? 1.单击删除按钮选中选项后,跳转到js函数,由函数处理 2. 主要就是前端的操作 js 操作(如何全选?如何把选中的数据传到Controller中) 3.fun()函数 ...