rocketv2 / reduxtodo Goto Github PK
View Code? Open in Web Editor NEW通过Todo实例,梳理redux生态
License: MIT License
通过Todo实例,梳理redux生态
License: MIT License
ref主要是用来获取dom对象,尤其是表单元素,如下代码:
<form onClick={this.eventHandler} onKeyDown={this.eventHandler} >
<input type="text" ref={this.refDom} />
<button type='submit'>add</button>
</form>
想获取input元素的值,显然不能使用jQuery的方式通过选择器来获取;而ref属性能够将dom对象作为形参传入函数中,此时函数this.refDom的形参就是input对象;
react采用虚拟DOM的目的是:减少DOM操作;但是ref属性操作的正是实际的DOM,这与react的理念相违背;
采用受控表单的方式;
<input type="text" value={this.state.getInputVal} onChange={this.getInputVal} />
项目中使用了prop-types库进行静态数据类型检查;这个是开发中必不可少的操作之一,能够降低引入bug的概率;
在产品环境中如何去掉prop-types库?
可以借助 babel-plugin-transform-react-remove-prop-types
在React v15.5.0 中,官方已经将 propTypes 从React库中独立出来,放在prop-types库中;这样做好处是:产品环境时并不使用propTypes进行检查,只是在开发环境中作为辅助工具,因此在产品环境中没必要使用这个库,减少上线代码体积;React把PropTypes放到一个独立包
组件父子之间通信 我们通常采用props,但是如果两个组件没有关联,比如是兄弟组件,如何在两者之间进行通信?通常做法是,找到这两个组件最近的父组件,进行状态提升,完成通信;
如果不想通过状态提升的方式,如何完成通信呢? 这就是pubsub.js库的作用,采用观察者模式,订阅事件后,如果某个组件发布这个事件,就能够触发订阅事件了;
pubsub库接口简单:publish(), subscribe(), unsubscribe()等;具体 官文文档
注意点:在componentWillUnmount钩子中要调用unsubscribe()
开发过程中如果需要使用静态数据,json格式是必不可少的选择;但是json在格式上存在一定的限制,比如书写格式限制等,不是很接近javascript语言风格;而json5正好解决了这个痛点,json5是JavaScript的子集,可以看做是对象类型,操作起来十分方便;
具体可以参考 json5官网
- jsx 注释用法: {/* 代码 */}
- 所有的标签都是闭合标签
- 使用内联样式时,style属性必须使用 {{}},第一层{}是表达式,第二次是传入的样式对象
<div style={{width: 20px; height=30px}}>
{ props.text }
</div>
比如开发todo组件,组件分成两部分:1. 添加 2. 展示;这两个部分是两个小组件;
如何将 组件1 中数据传入到 组件2 中呢?
通常采用 状态提升(lifting state up) 的方式;具体见 状态提升
但是,这种方式没有 状态管理 ,如果组件比较多,state就显得比较混乱;
因此引入了 redux 状态管理; redux 单向数据流,采用几个简单的API来控制数据单向流动;同时采用单一store,所有的组件都从唯一store中获取数据;
redux 基础API、工作流程
redux 中间件;重点为 异步请求的处理
react-redux的使用;为何引入react-redux?使用它带来了什么好处?
redux 中几个核心的概念: store,dispatch,subscribe,action
从redux库中引入的函数为 createStore,combineReducers,applyMiddleware,compose
- 通过createStore创建的对象包含以下接口
dispatch 分发action
getState 获取Store
subscribe 监听state,如果有改动,刷新函数
- combineReducers 将分割的reducer合并成一个reducer;
基于此,在设计store状态树时,要保持扁平化风格,尽量少些层级
- applyMiddleware 中间件
经常用于异步处理的中间件 redux-thunk
用于检测reducer是否是纯函数的中间件 redux-immutable-state-invariant
- compose 增强器
关于这部分基础,可以查看官方文档 ;也可以阅读 阮老师redux系列三篇
先说下,如果只使用redux提供的API,基本能够完成项目开发;
但是会遇到如下两个问题:
每次在组件中使用state时,都要引入store,通过store.getState()获取状态树;
每个组件为了便于开发,都采用 “UI组件 + 容器组件”的形式,其中UI组件负债UI展示,容器组件负责业务逻辑、数据处理(即dispatch action);但是容器组件结构简单,需要重复书写,如下:
/**
* UI组件
*/
const ListItem = ({itemInfo,changeStatus}) => {
let liItem = itemInfo.map((item,index)=>{
return (
<li
key={index}
onClick={changeStatus}
>
{item.text}
</li>
);
});
return (
<ul>
{liItem}
</ul>
);
}
ListItem.propTypes = {
itemInfo: PropTypes.array.isRequired,
changeStatus: PropTypes.func.isRequired
}
/**
* 容器组件
*/
class Container extends React.Component{
constructor(){
super(...arguments)
this.state = {
todos: Store.getState().todos
}
this.changeState = this.changeState.bind(this)
}
changeState(){
this.setState({
todos: Store.getState().todos
});
}
componentDidMount(){
Store.subscribe(this.changeState);
}
changeStatus(){
console.log('改变组件状态 完成、删除')
}
render(){
const items = this.state.todos;
return (
<ListItem
itemInfo={items}
changeStatus={this.changeStatus}
/>
);
}
}
react-redux 库解决了这两个问题,库提供了两个接口: Provider connect;
Provider 能够提供全局的store
connect 能够生成容器组件,开发者只需要提供UI组件即可;
快速入门 阮老师react-redux
在容器组件中dispatch回调函数,使用redux-thunk作为中间件,发现并未执行回调函数;代码如下:
const mapDispatchToProps = (dispatch) => {
return {
addItem: (val) => {
// 使用redux-thunk中间件
dispatch((val)=>{
return (dispatch,getState) => {
// 并未执行此处代码,在此进行异步处理
}
});
},
}
}
在dispatch中return的函数并未执行,因此无法进行异步处理
此问题困住了我很久,因为官方代码:
function incrementAsync() {
return dispatch => {
setTimeout(() => {
// Yay! Can invoke sync or async actions with `dispatch`
dispatch(increment());
}, 1000);
};
}
一直受这段代码影响,以为incrementAsync函数为disapcth的参数,redux-thunk中间会执行该函数;但实际结果跟猜测不一致,incrementAsync中的 return 返回的函数根本没有执行;无奈,只能看redux-thunk源码了,源码如下:
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
从源码中可以看出,dispatch的函数就是redux-thunk要回调的函数,形参是dispatch,getState;不需要return函数,redux-thunk不会执行return中的函数;正确的写法如下:
const mapDispatchToProps = (dispatch) => {
return {
addItem: (val) => {
// 使用redux-thunk中间件
dispatch((dispatch,getState) => {
// 并未执行此处代码,在此进行异步处理
});
},
}
}
以上是本人的理解,如有疑问,欢迎交流~~
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.