Redux学习(一)

Redux学习日志(一)

Redux中文文档:http://www.redux.org.cn/

阮一峰的网络学习日志:http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html

Redux是js的状态容器,提供可预测化状态管理

Redux除了和React一起用之外还支持 其他界面库

他体积小(2KB)而且没有任何依赖

什么时候使用

当UI层十分简单,没有很多互动,Redux就是不必要的,用了反而增加复杂性

  • 用户的使用方式十分简单
  • 用户之间没有写作
  • 不需要与服务器大量交互,也没有使用websocket
  • 视图层(view)只是从单一的来源获取数据

以上这些情况不需要使用

  • 用户使用方式复杂
  • 不同的身份有不同的适用方式(会员 普通用户)
  • 多个用户之间可协作(聊天室)
  • 与服务器大量交互,使用websocket
  • view要从多个来源获取数据

以上这些情况可以使用

如果应用不复杂可以不用

redux的设计思想

一 web应用是一个状态机,视图与状态一一对应

二 所有的状态,都保存在一个对象里

基本概念和API

store

store是保存数据的地方,整个应用只能有一个store

createStore函数可用来生成store

/*引入Redux*/
import { createStore } from "redux"
const store=createStore(fn)
  • 1
  • 2
  • 3

state

store对象包含所有的数据,如果想要得到某个时间点的数据,就要对store生成快照,这种时点的集合就叫做state

/*引入Redux*/
import { createStore } from "redux";
const store=createStore(fn)

const state=store.getState();
  • 1
  • 2
  • 3
  • 4
  • 5

一个state对应一个view

action

state的变换带动view的变化。但是用户接触不到state,用户接触到的是view层,当view层发生变化,会发出action,也就是说action是view发出的通知,表示state应该要产生变化

action是一个对象,其中type属性是必须的,表示action的名称,其他属性可自由设置,

const action={
  type:"TODO",     //action的名字
  payload:"Rexux"  //携带的信息是字符串 "Redxux"
}
  • 1
  • 2
  • 3
  • 4
action描述当前发生的事情,改变state是唯一的办法,就是使用action,他会把数据运送到store

action creator

view要发送多少种信息,就会有多少种action,如果都手写,比较的麻烦,可以定义一个函数来生成action,这个函数就是action creater

const ADD_TODO="添加 TODO";
function addtodo(params){
  return {
    type:ADD_TODO,
    params
  }
}

const action=addtodo("learn redux")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

addtodo函数就是一个 Action Creator

store.dispatch()

store.dispatch()是view发出action的唯一方法

import { createStore } from "redux";
const store=createStore(fn);
store.dispatch({
  type:"ADD_TODO",
  payload:"learn redux"
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

结合以上的addTodo函数,可简写成

store.dispatch(addTodo("learn Redux"))
  • 1

Reducer

store收到action之后,必须给出一个新的state,这样view才会发生变化,这种计算过程就叫做Reducer

Reducer是一个函数,他接受action和当前的state作为参数,返回新的state,


const reducer=function(state,action){ 
// 
return new_state 

这是一个例子

const defaultState=0;
const reducer=(state=defaultState,action)=>{
  switch(action.type){
    case "ADD":
        return state+store.payload;
    default:
        return state;   
  } 
}
//  
const state=reducer(1,{
  type:"ADD",
  payload:2
})
//输出3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

但在实际的应用中,并不会手动的调用Readucer,store.dispatch方法会触发Readucer的自动执行。为此,store、需要知道Readucer函数,所以需要在生成store的时候,将Readucer传入createStore方法

import { createStore } from "redux"
const store=createStore(reducer);
//createStore接收Reducerr作为参数,以后每当store.dispatch发送过来一个新的action,就会自动调用Readucer,得到新的State。
  • 1
  • 2
  • 3

纯函数

Reducer函数最重要的特征,他是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出

纯函数是函数式编程的概念,必须遵守一下一些约束,

函数式编程:函数是一等公民

  • 不得改写参数
  • 不能调用系统I/O的API
  • 不能调用Math.random或Data.now,因为每次得到的值不相同

store.subscribe()

store允许使用store.subscribe方法设置监听函数,一旦state发生变化,就会自动执行这个函数

import {createStore} from "redux";
const store=createStore(reducer)

store.subscribe(listener)
  • 1
  • 2
  • 3
  • 4

只要把view的更新函数放入listen,就会实现view的自动渲染

store.subscribe方法返回一个函数,调用这个函数可以解除监听

let unsubscribe=store.subscribe(()=>{
  console.log(store.getState)
})
  • 1
  • 2
  • 3

Store提供了三个方法

+ store.getState()
+ store.dispatch()
+ store.subscribe()
  • 1
  • 2
  • 3

在引入redux的时候

import { createStore } from "redux";
let { subscribe,dispatch,getState } = createStore(reducer)
  • 1
  • 2

createStore可以接受第二个参数

let store=createStore(fn,window.STATE_FROM_SERVER)
  • 1

window.STATE_FROM_SERVER就是整个应用的初始值,如果提供这个参数,他会覆盖Reducer函数的初始默认值

createStore方法的实现

const createStore=(reducer)=>{
  let state;
  let listeners=[];

  const getState=()=>state;

  //dispatch是view发出的action的唯一方法
  const dispatch=(action)=>{
    state=reducer(state,action);
    listeners.foreach(listener=>listener())
  };

  const subscripbe=(listener)=>{
    listeners.push(listener);
    return ()=>{
      listeners=listeners.filter(1=>1!listener);
    }
  };

  dispatch({});

  return {getState,dsipatch,subscribe};

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Reducer的拆分

Reducer可生成State,整个应用只有一个State对象,包含所有的数据,当State十分庞大的时候,Reducer函数也十分庞大。

例如

const chatReducer=(state=defaultState,action={})=>{
  const {type,payload}=action;
  switch (type){
    case ADD_CHAT:
        return Object.assign({},state,{
          chatLog:state.chatLog.concat(payloiad)
        });
    case CHANGE_STATUS:
        return Object.assign({},state,{
          statusMessage:payload
        });
    case CHANGE_USERNAME:
        return Object.assign({},state,{
          userName:payload
        });
    default:return state;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

以上代码中三种action分别改变state的三个属性

  • ADD_CHAT:chatlog属性
  • CHANGE_STATUS:statusMessage属性
  • CHANGE_USENAME:userName属性

Reducer提供combineReducer方法,用于Reducer的拆分

import {combineReducers} from "redux";

const chatReducer=combineReducer({
  chatLog:chatLog,
  userName:userName
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这段代码的意思是combineReducer方法将三个Reducer合并成一个大的函数;

猜你喜欢

转载自blog.csdn.net/qq_40963664/article/details/79466429
今日推荐