面试被问redux原理问懵逼了
1. redux出现的意义
在react中,数据在组件中是单向流动的,数据从一个方向父组件流向子组件都是通过props传值,两个非父子组件之间的通信就很麻烦,这时候redux就出现了。
2. redux视图
Redux是将整个应用状态存储到一个地方上称为store,里面保存着一个状态树store tree,组件可以派发(dispatch)行为(action)给store,而不是直接通知其他组件,组件内部通过订阅store中的状态state来刷新自己的视图。
3. Redux三大原则
1、唯一数据源
> 整个应用的state都被存储到一个状态树里面,并且这个状态树,只存在于唯一的store中
2、保持只读状态
> state是只读的,唯一改版state的方法就是触发action,action是一个用于描述以发生时间的普通对象
3、数据改变只能通过纯函数来执行
> 使用纯函数来执行修改,需要编写reducers来描述action如何改变state的。
4.Redux概念解析
1、**Store**
store 就是保存数据的地方,你可以把它看成一个数据,整个应用只能有一个store
Redux提供createStore这个函数,用来生成Store
import {createStore} from 'redux'
const store = createStore(fn)
5. State
state就是store里面存储的数据,store里面可以拥有多个state,Redux规定一个state对应一个View,只要state相同,view就是一样的,反过来也是,可以通过**store.getState()**获取
import {createStore} from 'redux'
const store = createStore(fn)
const state = store.getState()
6.Action
state的改变会导致view的变化,但是在redux中不能直接操作state也就是不能使用this.setState来操作,用户只能接触到View。在Redux中提供了一个对象来告诉Store需要改变state。Action是一个对象中type属性是必须的,表示Action的名称,其他的可以根据需求自由设置。
const action = {
type: 'ADD_TODO',
payload: 'redux原理'
}
在上面代码中,Action的名称是ADD_TODO,携带的数据是字符串’redux原理’,Action描述当前发生的事情,这是改变state的唯一方式
7. store.dispatch()
store.dispatch()是view发出Action的唯一方法
store.dispatch({
type:'ADD_TODO',
payload: 'redux原理'
})
store.dispatch接收一个Action作为参数,将他发送给store通知store来改变state。
8. Reducer
Store收到Action后,必须给出一个新的state,这样view才会发生变化,这种**state**的计算过程就叫做Reducer。
Reducer是一个纯函数,他接收Action和当前state作为参数,返回一个新的state。
Attention: Reducer 必须是一个纯函数,也就是说函数返回的结果必须由参数state和action决定,而且不产生任何副作用也不能修改state和action对象
const reducer = (state, action) => {
switch(action.type) {
case ADD_TODO:
return newstate;
default return state
}
}
9. Redux源码
let creatStore = (reducer) => {
let state
// 获取状态对象
// 存放所有的监听函数
let listeners = []
let getState = () => state
// 提供一个方法供外部调用派发action
let dispatch = (action) => {
// 调用管理员reducer得到新的state
state = reducer(state, action)
// 执行所有的监听函数
listeners.forEach((l) => l())
}
// 订阅状态变化事件,当状态发生变化之后执行监听函数
let subscribe = (listener) => {
listener.push(listener)
}
dispatch()
return {
getState,
dispatch,
subscribe
}
}
let combineReducers = (renducers) => {
// 传入一个renducers管理组,返回的是一个renducer
return function(state={}, action={}){
let newState = {}
for(var attr in reducers) {
newState[attr] = renducers[attr](state[attr], action)
}
return newState
}
}
export {createStore, combineReducers}
10. example
html 代码
<div id="counter"></div>
<button id="add"> + </button>
<button id="minus"> - </buttom>
js代码
function createStore(reducer) {
let state
let listener = []
let getState = () => state
let dispatch = (action) => {
state = reducer(state, action)
listeners.forEach(l => l())
}
let subscribe = (listener) => {
listeners.push(listener)
return () => {
listeners = listeners.filter((l) => l != listener)
}
}
dispatch()
return {
getState, dispatch, subscibe
}
}
let reducer = (state = 0, action) => {
if (!action) return state
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECRENT':
return state - 1
default:
return state
}
}
let store = createStore(reducer)
store.subcribe(function() {
document.querySelector('#counter').innerHTML = store.getState()
})
doucment.querySelector('#add').addEventListener('click', function() {
store.dispatch({type: 'INCREMENT'})
})
document.querySelect('#minus').addEventListener('click', function() {
store.dispatch({type: 'DECREMENT'})
})