该博文的内容紧跟上一篇博文,不清楚的可以先看上一篇:
redux学习笔记(一)地址:redux学习笔记(一)
Redux Dev Tools的安装
之前已经制作了Redux中state仓库,也可以从仓库中取出数据了。接下来我们需要在控制台调试这些仓库里的数据,需要使用Redux DevTools。安装这个是需要科学上网的,或者谷歌助手或自己找一些插件,所以你需要先找一个好梯子(如果没有安装的话,也不影响redux的使用)。
安装Redux DevTools
我使用Chrome浏览器安装插件,在浏览器右上角有三个点,然后点击"更多工具",再点击"扩展程序",再点击右侧的"打开Chrome网上商店",然后搜索Redux DevTools,可以看到下面这个插件,直接安装就可以了。
安装完成后,你在控制台中就可以看到Redux标签了,有了这个标签也说明安装成功了。
配置Redux Dev Tools
如何配置这个Redux Dev Tools插件,其实网站上已经说的非常清楚了,现在通过插件,打开这个网站。根据网站提示,我们把上一篇博文的./src/store/index.js代码改为下面的样子。
import { createStore } from 'redux' // 引入createStore方法
import reducer from './reducer'
const store = createStore(reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()) // 创建数据存储仓库
export default store //暴露出去
其实就是加了这样一句话.
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
这句话的意思就是看window里有没有这个方法,有则执行这个方法。
这步完成后,就可以启动项目测试一下了,你会发现State数据变的一目了然,以后再进行Redux调试,就会变的非常简单了。
通过Input体验Redux的流程
这里要做的就是通过Input的改变,体验一下Redux的整体流程,是如何编写代码的。我们要实现的是在TodoList的Demo中,只要文本框中的值改变就redux中store的值就跟着改变,并且随着Redux中的state值改变,组件也跟着改变。整个流程就是以前讲过的这个图,
增加Input响应事件
如果想Input改变,redux也跟着改变,需要在Input组件上增加onChange响应事件, 打开src目录下的ToDolist.js文件,修改具体代码如下:
<input placeholder="请输入" onChange={this.inputChange.bind(this)}/>
这步完成后,就可以编写inputChange方法的代码了。我们先在控制台打印出文本框的变化,代码如下:
inputChange (event){
// event.target.value这里是输入框的值
console.log(event.target.value)
}
然后打开浏览器,按F12看一下控制台的结果。这里给出目前的全部代码:
import React, { Component } from 'react';
import store from './store'
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
storeState:store.getState()
}
console.log(store.getState())
// 通过打印,可以看出拿到的是个对象,有两个属性inputValue , list
// 与store里面的属性一一对应
}
render() {
// 解构赋值
let {storeState}=this.state
return (
<div>
<div>
<input placeholder="请输入" onChange={this.inputChange.bind(this)}/>
<button>增加</button>
</div>
<ul>
{
storeState.list.map((item,index)=>{
return (
<li key={index}>{item}</li>
)
})
}
</ul>
</div>
);
}
inputChange (event){
// event.target.value这里是输入框的值
console.log(event.target.value)
}
}
export default TodoList;
下面需要作的事就是改变Redux里的值了,我们继续向下学习。
创建Action
想改变Redux里边State的值就要创建Action了。Action就是一个对象,这个对象一般有两个属性,第一个是对Action的描述,第二个是要改变的值。
inputChange (event){
// event.target.value这里是输入框的值
// console.log(event.target.value)
const action={
// type是对action的描述,必须有
type:'input-change',
// value是传递改变的值,可以没有
value:event.target.value
}
}
action就创建好了,但是要通过dispatch()方法传递给store。我们在action下面再加入一句代码。
inputChange (event){
// event.target.value这里是输入框的值
// console.log(event.target.value)
const action={
// type是对action的描述,必须有
type:'input-change',
// value是传递改变的值,可以没有
value:event.target.value
}
store.dispatch(action)
}
这是Action就已经完全创建完成了,也和store有了联系。
store的自动推送策略
前面已经说了store只是一个仓库,它并没有管理能力,它会把接收到的action自动转发给Reducer。我们现在先直接在Reducer中打印出结果看一下。打开store文件夹下面的reducer.js文件,修改代码。
export default (state=defualtState,action)=>{
console.log(state,action)
return state
}
讲到这里,就可以解释一下两个参数了:
- state: 指的是原始仓库里的状态。
- action: 指的是action新传递的状态。
通过打印你可以知道,Reducer已经拿到了原来的数据和新传递过来的数据,现在要作的就是改变store里的值。我们先判断type是不是正确的(当有多个更改的action时,可根据type判断,分别处理),如果正确,我们需要从新声明一个变量newState。(记住:Reducer里只能接收state,不能改变state。),所以我们声明了一个新变量,然后再次用return返回回去。
export default (state=defualtState,action)=>{
// console.log(state,action)
if (action.type==='input-change') {
let newState=JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.inputValue=action.value
return newState
}
return state
}
让组件发生更新
现在store里的数据已经更新了,但是组件还没有进行更新,我们需要打开组件文件TodoList.js
,在constructor,写入下面的代码。
constructor(props) {
super(props);
this.state = {
storeState:store.getState()
}
console.log(store.getState())
// 通过打印,可以看出拿到的是个对象,有两个属性inputValue , list
// 与store里面的属性一一对应
//-----关键代码-------开始
this.storeChagne=this.storeChagne.bind(this) //改变this指向
store.subscribe(this.storeChagne) //订阅redux的状态
// ----关键代码-------结束
}
当然我们现在还没有这个storeChange方法,只要写一下这个方法,并且重新setState一次就可以实现组件也是变化的。在代码的最下方,编写storeChange方法。
storeChagne () {
this.setState({
storeState:store.getState()
})
}
现在浏览器中预览,可以看到组件和Redux中都同步进行了改变。这里的内容比较多,把Redux的流程都走了一遍,如果坚持下来,也就算Redux入门了。可以把上面的代码多敲几遍,保证把基础知识打扎实。一定要动手作,不然真的学不会的。
Redux制作ToDoList列表
通过之前的知识,我们用同样的方法和流程,再开发一遍ToDoList里边的列表功能,具体来说就是当点击添加按钮时,ToDoList组件的列表会增加。知识其实我们都已经会了,缺少的是熟练度。
编写按钮添加响应事件和Action
先来编写按钮点击后的响应事件,打开TodoList.js文件,然后在增加按钮的地方加入onClick事件,
<button onClick={this.addItemAction.bind(this)}>增加</button>
绑定之后就可以编写addItemAction()方法了,这里先用一个打印语句代替业务内容。
addItemAction () {
console.log('add')
}
这时候预览一下,点击"增加按钮",在控制台就可以输出add了。说明我们的事件添加成功了
创建action并用dispatch()传递给store
在addItemAction方法里增加action,然后用dispatch()方法传递给store,代码如下:
addItemAction () {
const action={
type:'addItem'
}
store.dispatch(action)
}
这时候已经把action传递给了store,然后去Reducer里编写业务逻辑就可以了。
编写Reducer的业务逻辑
打开reducer.js
文件,先编写代码判断type是不是addItem,如果是向redux的list中插入新值。
export default (state=defualtState,action)=>{
// console.log(state,action)
if (action.type==='input-change') {
let newState=JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.inputValue=action.value
return newState
}
//关键代码------------------start----------
//state值只能传递,不能直接改变
if (action.type==='addItem') {
let newState=JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.list=[...newState.list,newState.inputValue]
// 上面的代码等价于 newState.list.push(newState.inputValue)
return newState
}
//关键代码------------------end----------
return state
}
因为上面之前已经编写了订阅方法,所以到这里就可以打开浏览器进行预览了。你可以试着添加一些新的东西进来。虽然没有什么新的知识点,但是这个Redux的流程你必须要熟练掌握,因为在工作中编写Redux程序,几乎每天都在和这个流程打交道,实现界面的快速响应。
用Redux实现ToDoList的删除功能
这里再来走一遍Redux的流程,用Redux来制作一下删除功能。其实就是在点击ToDoList中的列表子项时,删除对应的子项。
绑定子项响应事件
打开src目录下的TodoList.js
文件,然后找到render()中的li标签,编写如下代码:
<ul>
{
storeState.list.map((item,index)=>{
return (
<li key={index}
onClick={this.deleteItem.bind(this,index)}
>{item}</li>
)
})
}
然后编写这个deleteItem()方法,记得它需要接收一个index参数。
deleteItem (index) {
const action={
type:'delete-item',
index // 这里相当于index:index 的简写
}
store.dispatch(action)
}
reducer业务逻辑的实现
if(action.type==='delete-item'){
let newState=JSON.parse(JSON.stringify(state)) //深度拷贝state
newState.list.splice(action.index,1) //删除数组中对应的值
return newState
}
这时候就做完了这个TodoList组件的基本功能,当然,这个案例还是有很多不足的,我们需要学习更多的知识来完善它。