手写 redux 和 react-redux
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的更多相关文章
- 推荐使用并手写实现redux-actions原理
@ 目录 一.前言 二.介绍 2.1 创建action 2.2 reducer 2.3 触发action 三. 认识与手写createAction() 3.1 用法 3.2 原理实现 四.认识hand ...
- React深入 - 手写redux api
简介: 手写实现redux基础api createStore( )和store相关方法 api回顾: createStore(reducer, [preloadedState], enhancer) ...
- 手写一个Redux,深入理解其原理
Redux可是一个大名鼎鼎的库,很多地方都在用,我也用了几年了,今天这篇文章就是自己来实现一个Redux,以便于深入理解他的原理.我们还是老套路,从基本的用法入手,然后自己实现一个Redux来替代源码 ...
- react + redux 完整的项目,同时写一下个人感悟
先附上项目源码地址和原文章地址:https://github.com/bailicangd... 做React需要会什么? react的功能其实很单一,主要负责渲染的功能,现有的框架,比如angula ...
- 手写redux方法以及数组reduce方法
reduce能做什么? 1)求和 2)计算价格 3)合并数据 4)redux的compose方法 这篇文章主要内容是什么? 1)介绍reduce的主要作用 2)手写实现reduce方法 0)了解red ...
- 手写一个React-Redux,玩转React的Context API
上一篇文章我们手写了一个Redux,但是单纯的Redux只是一个状态机,是没有UI呈现的,所以一般我们使用的时候都会配合一个UI库,比如在React中使用Redux就会用到React-Redux这个库 ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- react+redux教程(八)连接数据库的redux程序
前面所有的教程都是解读官方的示例代码,是时候我们自己写个连接数据库的redux程序了! 例子 这个例子代码,是我自己写的程序,一个非常简单的todo,但是包含了redux插件的用法,中间件的用法,连接 ...
- react+redux教程(六)redux服务端渲染流程
今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...
随机推荐
- Python_编程题集_001_词法解析
1.词法解析: 我的是名字是ths,今年18岁 语法分析后得到结果如下: 数字:18 中文:我的名字是 今年 岁 拼音:ths 符号:,. 请编写程序实现该词法分析功能 string模块解: impo ...
- JAVA复制
复制 直接赋值 直接赋值.在 Java 中, A a1 = a2,我们需要理解的是这实际上复制的是引用,也就是说 a1 和 a2 指向的是同一个对象.因此,当 a1 变化的时候, a2 里面的成员变量 ...
- 18,OS模块
import os print(os.getcwd())#执行所在的目录 # os.makedirs('\python作业\景s12\day18')#可生成多层递归目录 # os.mkdir('\py ...
- 大数据学习——scala入门程序
安装scala.msi https://blog.csdn.net/sinat_32867867/article/details/80305302 notepad++ object HelloScal ...
- Python --链接Mongodb
# -*- coding: UTF-8 -*- from pymongo import MongoClient # 数据库连接 class MongoDB(object): def __init__( ...
- hlgoj1881
#include <stdio.h> +]; int main(){ int l,m; int i,j; int sign; num[]=; num[]=; while(~scanf(&q ...
- msp430项目编程51
msp430综合项目---扩展项目一51 1.电路工作原理 2.代码(显示部分) 3.代码(功能实现) 4.项目总结
- awk 对简单文本处理试水
#juanjuan是一个文件 [root@localhost c_test]# cat juanjuan , , bffd97d0 , , bffd97cc , , bffd97c8 , , #-F ...
- Laravel 控制器的middleware中间件
场景:活动开始前只能访问宣传页面,开始后才可以访问其他页面: 步骤: 新建中间件, 注册中间件, 使用中间件, 中间件的前置和后置操作. 控制器: public function activity0( ...
- linux top %VSZ含义
https://blog.csdn.net/sinohenu/article/details/58216013 https://unix.stackexchange.com/questions/449 ...