redux-simple 简化版的redux
作为react的粉丝,当然要吐槽一下react组件通信问题。react的单向数据流是组件通信的一大阻碍,只允许父组件向子组件传值,子组件向父组件传值只能通过父组件向子组件传递回调函数实现。如果在深层次的组件结构当中,复杂与繁多的回调会大大增加程序的维护难度与可读性,延长开发周期。即使react实现的再优秀,组件通信没处理好,还是一坨屎。redux给react的组件通信带来解决方案:构建一个大的状态作用域(一个大组件),大组件里的所有组件状态变化都只需要维护大组件,更新的状态都有大组件开始下发,这样就避免了子组件向父组件传值需要回调方法的问题。
redux优点:贯彻了react的单向数据流思想,避免父子组件通信时繁琐的回调,清晰的数据流简化了业务逻辑实现,提高应用维护效率。
redux槽点:为了数据中心化与自动化测试分离出了action与redcuer与mapStateToProps,简单的数据操作被复杂化了。每次dispatch都会重新渲染状态作用域里的所有组件,虽然react使用diff算法筛选出需要改变的节点进行渲染(优化了性能),但是在庞大以及深层次的组件结构中,diff带来的消耗还是不可忽视的。
我格外厌恶redux繁琐的操作,所以自己实现了一个简化版的redux。把action与redcuer合并、废弃了mapStateToProps简化了redux的数据操作。由于action与redcuer的合并后存在数据依赖,所以合并后的action不能做数据自动化测试。除了简化redux的繁琐的数据操作之外,还通过监听组件里的动态数据与dispatch更新的数据对比检测该组件是否需要重新渲染,解决redux最大的弊端【redux组件渲染弊端:redux dispatch后没有变化的组件也会被重新渲染,这是不必要的性能消耗】。我还丰富了Component基类给每个组件提供了重新渲染检测功能。
redux-simple.s实现如下:
- import React,{Component,createElement} from "react";
- var event=function(){
- var propsment={};
- var dispatchProps={};
- return {
- //添加监听属性
- listenProps:function(props,_this){
- if(_this.constructor&&_this.constructor.name){
- propsment[_this.constructor.name]=props;
- }else{
- throw new Error("监听对象不是react组件");
- }
- },
- //清空监听的属性
- emptyProps:function(){
- propsment={};
- },
- //检测是否需要更新
- checkProps:function(_this){
- var data=propsment[_this._reactInternalInstance.getName()]||[];
- var propKeys=Object.keys(dispatchProps);
- //没有监听属性的组件直接更新
- if(!data.length){
- return true;
- }
- for(var i=0;i<data.length;i++){
- //判断监听的属性是否存在于更新数据里面,存在则更新组件
- if(propKeys.indexOf(data[i])!=-1){
- return true;
- }
- }
- return false;
- },
- //监听更新的数据
- listenDispatch:function(props){
- dispatchProps=props;
- }
- }
- }()
- export function connect(App,actions){
- let dispatch,getState;
- dispatch=getState=function(){
- throw new Error("组件还没初始化");
- }
- class Main extends Component{
- constructor(props){
- super(props);
- this.constructor.setState=dispatch=(data)=>{
- //监听更新的数据
- event.listenDispatch(data);
- //更新store
- this.setState(Object.assign({},this.state,data));
- }
- getState=()=>{
- return Object.assign({},this.state);
- }
- this.actions=bindAction(actions,dispatch,getState||{});
- }
- render(){
- return <div>
- {createElement(App,Object.assign({dispatch:dispatch,listenProps:event.listenProps,getState:getState,actions:this.actions},this.props,this.state))}
- </div>
- }
- }
- return Main;
- }
- //action方法绑定dispatch并支持异步
- function bindActionCreators(action,dispatch,getState){
- if(typeof action==="function"){
- return function(){
- [].unshift.call(arguments,getState());
- var newState=action.apply(null,arguments);
- if(typeof newState==="function"){
- newState(dispatch)
- }else if(isObject(newState)){
- dispatch(newState);
- }else{
- throw new Error("action方法返回值只能是函数或者对象");
- }
- }
- }
- }
- //给所有的action方法绑定dispatch
- export function bindAction(actions,dispatch,getState){
- var newActions={};
- if(isObject(actions)){
- var keys=Object.keys(actions);
- keys.forEach(function(value){
- newActions[value]=bindActionCreators(actions[value],dispatch,getState)
- })
- return newActions;
- }else if(actions){
- throw new Error("actions必须是对象")
- }
- }
- //检测是否是一个对象
- let isObject=(data)=>{
- if(Object.prototype.toString.call(data)=="[object Object]"){
- return true;
- }else{
- return false;
- }
- }
- //构建新的组件基类
- export default class NewCom extends Component{
- shouldComponentUpdate(nextProps){
- return event.checkProps(this,nextProps); //检测是否重新渲染该组件
- }
- componentWillUnmount(){
- event.emptyrProps(); //清空监听列表
- }
- }
使用实例如下:
- import ReactDom from "react-dom";
- import React from "react";
- import Component,{connect} from "./react-extend.js";
- import * as actions from "./action/test.js";
- class Test01 extends Component{
- constructor(props){
- super(props);
- this.props.listenProps(["test01"],this); //监听该组件的动态数据
- }
- render(){
- return <h1>{this.props.test01}</h1>
- }
- }
- class Test02 extends Component{
- constructor(props){
- super(props);
- this.props.listenProps(["test02"],this); //监听该组件的动态数据
- }
- clickHandler(){
- this.props.actions.changeTest01(789);
- }
- render(){
- return <h1 onClick={this.clickHandler.bind(this)}>{this.props.test02}</h1>
- }
- }
- class Main extends Component{
- componentDidMount(){
- this.props.actions.init({
- test01:123,
- test02:456,
- })
- }
- render(){
- return <div>
- <Test01 {...this.props}/>
- <Test02 {...this.props}/>
- </div>
- }
- }
- var NewMain=connect(Main,actions);
- ReactDom.render(
- <NewMain />,
- document.getElementById("container")
- )
action:
- export function changeTest01(state,value){
- return {
- test01:value,
- }
- }
- export function init(state,obj){
- return obj;
- }
redux-simple 简化版的redux的更多相关文章
- redux源码解析-redux的架构
redux很小的一个框架,是从flux演变过来的,尽管只有775行,但是它的功能很重要.react要应用于生成环境必须要用flux或者redux,redux是flux的进化产物,优于flux. 而且r ...
- react第十六单元(redux的认识,redux相关api的掌握)
第十六单元(redux的认识,redux相关api的掌握) #课程目标 掌握组件化框架实现组件之间传参的几种方式,并了解两个没有任何关系组件之间通信的通点 了解为了解决上述通点诞生的flux架构 了解 ...
- [Redux + Webpack] Hot reloading Redux Reducers with Webpack
Webpack will hot reload the component, but the reducer we need hard refresh. To sovle the problem, g ...
- Redux学习笔记:Redux简易开发步骤
该文章不介绍Redux基础,也不解释各种乱乱的概念,网上一搜一大堆.只讲使用Redux开发一个功能的步骤,希望可以类我的小白们,拜托它众多概念的毒害,大牛请绕道! 本文实例源代码参考:React-Re ...
- redux sample with slim redux source code
code sample没有package.json文件,也就没有任何外部依赖,直接使用slim redux source code. slim resux只有90多行. nodejs对es6的impo ...
- [Redux] Important things in Redux
Root Smart component can be overloaded, divide 'smart' component wisely & using Provider. Proble ...
- 1.Redux学习1,Redux
Redux流程图如上: Action就是一条命令 Store顾名思义就是存储数据的, Reducers是一个回调函数用于处理数据,它处理完数据会返回给Store存储起来 基本流程就是:组件中用Stor ...
- 4 react 简书 引入 redux 的 combineReducers 对 redux 数据进行管理
1. src 下的 common 下的 header 创建 store 文件夹 下创建 reducer.js # src/common/header/store/reducer.js const st ...
- React之redux学习日志(redux/react-redux/redux-saga)
redux官方中文文档:https://www.redux.org.cn/docs/introduction/CoreConcepts.html react-redux Dome:https://co ...
随机推荐
- Kafka笔记--指定消息的partition规则
参数的设定:参考资料 不错的资料:http://blog.csdn.net/honglei915/article/details/37697655 http://developer.51cto.com ...
- 浏览器的模式问题 Quirks Mode vs Standards Mode
当微软开始产生与标准兼容的浏览器时,他们希望确保向后兼容性.为了实现这一点,他们IE6.0以后的版本在浏览器内嵌了两种表现模式: Standards Mode(标准模式或Strict Mode)和Qu ...
- 使用JQUERY实现局部页面定时刷新
没办法,运维会一点点前端,还是有好处的.. 说不定,BOOTSTRAP也得会一点点.. 本想用流式输出的搞定的,但没搞定,就取巧了... 代理简单: <script src="//cd ...
- 一张图看懂片式多层陶瓷电容器(MLCC)
- DC-DC转换器原理与应用
DC/DC转换器为转变输入电压后,有效输出固定电压的电压转换器.DC/DC转换器分为三类:升压型DC/DC转换器.降压型DC/DC转换器以及升降压型DC/DC转换器.根据需求可采用三类控制.PWM控制 ...
- Codec plugins ? multiline
Codec plugins ? multiline multiline codec 会折叠多行消息,合并它们到一个事件 这个codec 原始的目的是允许 连接多行信息从文件到一个单独的事件. 比如, ...
- 深入JS系列学习2
今天看和学习了深入理解JS系列2.3.4.5,更加明白了函数声明和表达式的区别,自执行函数和立即执行函数,js强大的原型链继承,js中对象的想过写法,modules模式等. 在ECMAScript中, ...
- vs 2013调试的时候重启的解决方案
今天在用vs 2013 调试程序的时候,vs 总是莫名其妙的关闭,停止运行,泪蹦了..... 是什么原因呢? 以前的时候可是好好的啊,经过认真的思索,最近装过和vs 2013 相关的程序也只有 ref ...
- Java的多线程(上)
多线程的优点和必要性是不言而喻的. 三种方法实现多线程 1. 继承Thread class A extends Thread{ public void run() {...} } 使用时, new A ...
- Confluence简介
前言 我们有很多的知识共享的工具,比如我们每天都用的qq共享,网盘共享,但是都不如我们这个来的方便,直接.这个是直接通过网页的形式进行共享,类似于我们的博客共享,但是它更加的具有指向性,站点管 ...