1、web应用是一个状态机,视图和状态是一一对应的
2、所有的状态,保存在一个对象里面
Store就是保存数据的地方,可以理解成一个容器。整个应用只能有一个store。
import { createStore} from 'redux';
const store = createStore(func)
上面的代码会返回一个新的store对象。
State对象包含所有数据。Redux规定,一个State对应一个View,所以State什么样,View就是什么样的。
import { createStore } from 'redux';
const store = createStore(fn);
const state = store.getState();
上面的代码可以取到当前的state数据。
我们知道State的变化会导致View的变化,但是用户接触不到State,只能接触到view。
Action就是从View发出通知,State接受并表示变化。
Action是一个对象,其中的 type 属性是必须的,表示Action的名称。
const action = {
type: 'ADD',
}
store.dispatch()是View发出Action的唯一方法。
import { createStore } from 'redux';
const store = createStore(fn);
const action = {
type: 'ADD',
value: '新数据'
}
store.dispatch(action)
store.dispatch接受一个 Action 对象作为参数,将它发送出去。
store.subscribe可以监听到dispatch发送出去的数据,一旦State发生变化,自动执行该函数。
import { createStore } from 'redux';
const store = createStore(reducer);
store.subscribe(()=>{
//数据发生了变化
});
store.subscribe()方法返回一个函数,调用这个函数就可以解除监听。
let unSubscribe = store.subscribe(()=>{
//数据发生了变化
});
unSubscribe ()
Store收到Action后,必须给一个新的State,这样View才会更新。这种计算过程叫做Reducer。
Reducer是一个函数,接受State、Action作为参数,返回一个新的State。
const reducer = (state = 0, action)=>{
switch (action.type) {
case 'ADD':
return state + 1
case 'DEL':
return state - 1
default:
return state;
}
}
const store = createStore(reducer)
由于Reducer是纯函数,它里面的State都是一样的,这样View也是一样的,所以Reducer函数里面不能改变State,必须返回一个新的State。
function reducer(state, action) {
return Object.assign({}, state);
}
在实际开发中,因为只有一个State对象,包含了所有的数据,对大型项目来说,这个State必然非常庞大。
Redux提供了一个combineReducers方法,用于Reducer的组合,只需要定义多个Reducer函数,用这个方法合并就可以了。
const Cat = (state = 0, action)=>{
return Object.assign({}, state);
}
const Dog = (state = 0, action)=>{
return Object.assign({}, state);
}
let reducers = combineReducers({ Cat, Dog })
createStore(reducers)
//main.js
import ReactDOM from 'react-dom';
import App from './component/App';
import store from './store';
const render = () => {
ReactDOM.render(<App
store={store.getState()}
dispatch={store.dispatch}
/>, document.getElementById('root'));
}
render()
store.subscribe(render)
上面是一个简单的页面,我们把state的值和dispatch方法,做为参数传给App组件,Store的监听函数设置为render,每次改变State的时候会渲染这个页面。
// ./component/App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = { };
}
removeItem = (key) => {
this.props.dispatch({ type: 'DEL', key: key })
}
handleClick = (e) => {
var value = this.refs.input.value;
this.props.dispatch({type: 'ADD', value: value})
}
render() {
return (
<div>
<input type="text" ref="input"/>
<button onClick={this.handleClick}>添加</button>
<br/>
<ul>
{
this.props.store.list.map((v, k)=>{
return (
<li key={k}>{v} <button onClick={this.removeItem.bind(this, k)}>X</button></li>
)
})
}
</ul>
</div>
);
}
}
在App组件中,我们可以用this.props拿到store和dispatch。
// store.js
import { createStore } from 'redux';
const initState = {
name: '这是name',
list: [
'测试数据1',
'测试数据2'
]
}
const = reducer = (state = initState, action)=>{
switch (action.type) {
case 'ADD':
state.list = [...state.list, action.value]
return Object.assign({}, state)
case 'DEL':
state.list.splice(action.key, 1)
return Object.assign({}, state)
default:
return state;
}
}
const store = createStore(reducer)
export default store