1.手写 redux

redux.js

/**
* 手写 redux
*/
export function createStore(reducer) {
// 当前状态
let currentState;
// 监听队列
let currentListeners = [];
// 订阅(观察)
function subscribe(listener) {
// 将listener放入数组
currentListeners.push(listener);
// return 一个方法 取消注册
return function() {
currentListeners = currentListeners.filter(function(l) {
return l !== listener;
})
}
}
// 分发
function dispatch(action) { // 接收 action 对象
/**
* 处理完得到的结果,给当前的状态
* 执行外部传入的 render 方法
*/
currentState = reducer(currentState, action);
/**
* 将订阅者方法 挨个执行一次
*/
currentListeners.forEach((v) => v())
}
// 获取状态值
function getState() {
// 返回当前值
return currentState;
} // 返回的是个 store 对象
return {subscribe, dispatch, getState}
} /**
* 用于 react-redux 调用
*/
export function bindActionCreator(creator, dispatch) {
// 包装一下
return (...args) => {dispatch(creator(...args))}
} export function bindActionCreators(creators, dispatch) {
let bound = {};
Object.keys(creators).forEach(v => {
let creator = creators[v];
bound[v] = bindActionCreator(creator, dispatch);
}) return bound;
}

2.手写 react-redux

myReactRedux.js

/**
* 手写 react-redux
* Provider -> context 技术。可以跨级来使用属性。
*/
import React, { Component } from 'react';
// 类型检查
import PropTypes from 'prop-types';
// 引入手写的redux
import { bindActionCreators } from './redux'; // connect 方法 -- 用于获取数据
export function connect(mapStateToProps=state=>state, mapDispatchToProps={}) { // 高阶组件(方法) -- 去状态的组件
/**
* mapStateToProps 把 状态 转成 属性
* mapDispatchToProps 把 action方法 转成 属性
* react 性能优化最主要的一点是减少状态的使用,将值转为this.props的属性值来代替
*/
// 柯里化
return function(OldComponent) {
return class NewComponent extends Component {
static contextTypes = {
store: PropTypes.object // 类型与外部相同
}
// 构造函数
constructor(props, context) {
super(props, context); this.state = { // 定义内部状态
props: {
...props // 拆分符
}
};
} // 生命周期 -- 首次加载之后调用
componentDidMount(){
// 添加监听
const store = this.context.store;
store.subscribe(() => this.update());
this.update();
} update(){
const store = this.context.store;
const stateProps = mapStateToProps(store.getState()); // 把store中的数据,变为react组件的props属性
// 把原有的 action 加工, 返回 dispatch(action)
const dispatchProps = bindActionCreators(mapDispatchToProps, store.dispatch);
this.setState({
props: { // 将传入的对象的值作为props的属性
...this.state.props,
...stateProps,
...dispatchProps
} // 类型于对象合并
})
} render(){
return <OldComponent {...this.state.props} />
}
}
}
} // /**
// * 上述代码 es6 写法
// * 函数柯里化
// */
// export const connect = (mapStateToProps, mapDispatchToProps) => (OldComponent) => {
// // 接收旧的组件,返回新的组件
// return class NewComponent extends Component {
// //...
// }
// } // 创建 Provider 组件(类) -- 使得任何内容都可以直接在组件内通过 connect 使用 store
export class Provider extends Component {
// 构造函数
constructor(props, context) { // context 上下文
super(props, context); this.store = props.store; // 得到传入的store属性
}
/**
* 定义静态对象
* 类型校验 -- 确定是由哪个组件提供的store
*/
static childContextTypes = {
store: PropTypes.object
};
// 获取 child 上下文
getChildContext(){
// 向外提供,便于Provider所有子组件调用
return {store: this.store}
}
// 直接渲染Provider的子组件
render() {
return this.props.children;
}
}

3.测试

demo.js

/**
* 引入 redux
* reducer 和 action 会写在一个文件中
*/
// import { createStore } from 'redux';
import { createStore } from './redux'; // reducer
function inputChange(state = 10, action) {
switch(action.type){
case 'add': // 加
return state + 1;
case 'sub': // 减
return state - 1;
default: // 默认
return state;
}
} // 定义store
const store = createStore(inputChange); // 通过 subscribe 订阅数据流
store.subscribe(listener); // 23中设计模式 -- 观察者模式 function listener(argument) {
const current = store.getState();
console.log(`当前数据:${current}`);
} console.log(store.getState()); // 10 store.dispatch({type: 'add'}); // 11
store.dispatch({type: 'add'}); // 12
store.dispatch({type: 'sub'}); // 11 /**
* 隐式转换 -- 优先级 -- 转换顺序
* Object 高级数据结构 可以转换成 String/Boolean/Number 初级数据结构
*/
console.log({}.length); // undefined
console.log(({}+{}).length); // 30 -- string 优先级高于 number 所以变成字符串相加 -- [object Object] [object Object] 30

.

手写 redux 和 react-redux的更多相关文章

  1. 推荐使用并手写实现redux-actions原理

    @ 目录 一.前言 二.介绍 2.1 创建action 2.2 reducer 2.3 触发action 三. 认识与手写createAction() 3.1 用法 3.2 原理实现 四.认识hand ...

  2. React深入 - 手写redux api

    简介: 手写实现redux基础api createStore( )和store相关方法 api回顾: createStore(reducer, [preloadedState], enhancer) ...

  3. 手写一个Redux,深入理解其原理

    Redux可是一个大名鼎鼎的库,很多地方都在用,我也用了几年了,今天这篇文章就是自己来实现一个Redux,以便于深入理解他的原理.我们还是老套路,从基本的用法入手,然后自己实现一个Redux来替代源码 ...

  4. react + redux 完整的项目,同时写一下个人感悟

    先附上项目源码地址和原文章地址:https://github.com/bailicangd... 做React需要会什么? react的功能其实很单一,主要负责渲染的功能,现有的框架,比如angula ...

  5. 手写redux方法以及数组reduce方法

    reduce能做什么? 1)求和 2)计算价格 3)合并数据 4)redux的compose方法 这篇文章主要内容是什么? 1)介绍reduce的主要作用 2)手写实现reduce方法 0)了解red ...

  6. 手写一个React-Redux,玩转React的Context API

    上一篇文章我们手写了一个Redux,但是单纯的Redux只是一个状态机,是没有UI呈现的,所以一般我们使用的时候都会配合一个UI库,比如在React中使用Redux就会用到React-Redux这个库 ...

  7. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

  8. react+redux教程(八)连接数据库的redux程序

    前面所有的教程都是解读官方的示例代码,是时候我们自己写个连接数据库的redux程序了! 例子 这个例子代码,是我自己写的程序,一个非常简单的todo,但是包含了redux插件的用法,中间件的用法,连接 ...

  9. react+redux教程(六)redux服务端渲染流程

    今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...

随机推荐

  1. pandas.DataFrame——pd数据框的简单认识、存csv文件

    接着前天的豆瓣书单信息爬取,这一篇文章看一下利用pandas完成对数据的存储. 回想一下我们当时在最后得到了六个列表:img_urls, titles, ratings, authors, detai ...

  2. python-小数据池,再谈编码,is和 == 的区别

    一 . 小数据池 # 小数据池针对的是: int, str, bool 在py文件中几乎所有的字符串都会缓存. # id() 查看变量的内存地址 s = 'attila' print(id(s)) 二 ...

  3. DELL R730 服务器拷贝大文件

    从服务器上拷贝大文件,通过USB拷贝,写入速度很慢,而且拷贝到100多G的时候直接卡死. 原因:服务器的USB是2.0,传输速率很慢. 解决方法: 找一台笔记本,USB 接口是3.0的,通过网络共享传 ...

  4. LeetCode(90) Subsets II

    题目 Given a collection of integers that might contain duplicates, nums, return all possible subsets. ...

  5. apk 解包 打包

    APK应用程序的解包.修改.编辑.汉化.打包及应用 前两讲主要讲玩机的最基本的知识,集中在如何刷机.本讲是进级的内容,来谈谈与apk应用程序有关的知识,内容包括akp文件的解包.打包.反编辑.解析.汉 ...

  6. 【php学习之路】微信公众帐号

          上个月开始学习php,算上中间放假的时间差不多有一个月了.这段时间呢,每天上班没事的时候不慌不忙的看下php,刚开始也只是看下php中文手册,看完一遍好像没什么感觉.于是就想啊,做个什么东 ...

  7. hdu6073[dfs+删边] 2017多校4

    题目中对二分图的定义十分特殊, 指的是 U,V两部分中,U的顶点度数必定为2,V中顶点无限制. 题目要求的是 对于所有匹配,该匹配的权值=该匹配中选中的边的边权的乘积,求所有匹配权值之和. 对于V中的 ...

  8. BZOJ 3209: 花神的数论题【数位dp】

    Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了. ...

  9. java面试题之能创建volatile数组吗?

    答:能,只不过只是一个指向数组的引用,而不是整个数组,如果改变了引用指向的数组,将会受到volatile的保护,但是如果多个线程同时改变数组的元素,volatile关键字就不能起到保护的作用.

  10. day2之爬取拉勾网

    认证流程 浏览器清空cookies 步骤一 访问拉勾网网站  https://www.lagou.com/ 做了些什么: 以get方式请求"https://www.lagou.com/&qu ...